Repository: projectcontour/contour

Issue:
Overload Manager - Max Global Downstream Connections
Part of the edge best practices for running envoy, in addition to the max-heap resource monitors, there's a global connection limit set,
https://www.envoyproxy.io/docs/envoy/latest/configuration/best_practices/edge#best-practices-edge

>
>```yaml
>layered_runtime:
>  layers:
>  - name: static_layer_0
>    static_layer:
>      envoy:
>        resource_limits:
>          listener:
>            example_listener_name:
>              connection_limit: 10000
>      overload:
>        global_downstream_max_connections: 50000
>```

This is particularly helpful for one of our cases where the connections came in so rapidly that the heap resource monitor based actions couldn't kick in and envoy ended up in a death loop.

Adding the limit itself is not particularly invasive, however, an extension of that our requirements was to make it possible to fail readiness checks, but keep passing liveness checks which leads to some extra listener configuration requirements. The way I've addressed this is by using the [`ignore_global_conn_limit `](https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/listener/v3/listener.proto#envoy-v3-api-field-config-listener-v3-listener-ignore-global-conn-limit) on the configured stats admin listeners. By default all listeners _**ignore**_ the connection limit, but we add an optional configuration to setup a listener that has the flag set to `false`. 

The Draft PR I've opened (https://github.com/projectcontour/contour/pull/6308) does a minimal configuration update, but it it makes for a very cumbersome interactions between the serve-context config, the contour config CRD, and how it's passed to the underlying internal envoy package. Before I make any other changes (and add more tests, etc.) I'd like to get some feedback on a better path forward re: configuration. 

My proposal would be to shift the configuration of the listeners up to the serve command, which would be responsible for constructing the listener configurations from it's parameters, effectively moving the core branch logic out of `v3.StatsListeners` to  `main.doServe`. I see an added benefit of reducing how deep the contour apis get passed into the internal components and it keeps the configuration isolated to the serve command instead of having it distributed to the inner parts. I suspect this may simplify some of the test configuration as well so we don't have tor rely on assumptions about the listeners returned (eg, taking the first listener https://github.com/projectcontour/contour/blob/main/internal/featuretests/v3/envoy.go#L597 and taking that for granted in the discovery responses)

I wrote a proof of concept change to illustrate what that might look like, which if reasonable will implement in my draft (https://github.com/projectcontour/contour/pull/6308)
https://github.com/projectcontour/contour/compare/main...seth-epps:options-listener-config?expand=1

Hints from issue comments:
@davinci26: cc @projectcontour/maintainers@sunjayBhatia: > My proposal would be to shift the configuration of the listeners up to the serve command

An issue with this is Gateway API Gateway reconciliation, Listeners can be dynamically changed without a contour restart/recreate so they do need to be generated similarly to other resources@sunjayBhatia: > > My proposal would be to shift the configuration of the listeners up to the serve command
> 
> An issue with this is Gateway API Gateway reconciliation, Listeners can be dynamically changed without a contour restart/recreate so they do need to be generated similarly to other resources

ah i guess this is just concerning the admin/operator facing Listeners so maybe disregard this point@sunjayBhatia: To summarize some of the context from here and what we have available today:
- we do have per-Listener downstream connection limits available, but these apply only to the HTTP/HTTPS listeners for proxying app traffic, not stats/health/admin Listeners: https://github.com/projectcontour/contour/blob/a485abb0a595c55f03239451cf0731f1d4fdf86f/apis/projectcontour/v1alpha1/contourconfig.go#L436
- a global connection limit would be enforced in tandem with per-Listener limits, i.e. you can set a per-Listener limit lower than the global limit
- having a Listener ignore the global limit means their downstream connections still count against the limit but connections to that Listener are not limited
- in the original issue content we have an example configuring the global connection limit via runtime key, but that method is deprecated so we need to configure it via bootstrap overload manager resource monitor

It makes sense to me to leave the stats endpoints to ignore the global limit, we still want to be able to serve readiness checks and stats even when envoy is overloaded. the admin Listener (listens on a Unix domain socket) should also be made to ignore the global limit as well.

I think in general the linked PR looks like it should work just fine, only thing is on the readiness/liveness check note from above:

> an extension of that our requirements was to make it possible to fail readiness checks, but keep passing liveness checks

at the moment the base install YAMLs don't include a liveness check, only a readiness check (see: https://github.com/projectcontour/contour/blob/a485abb0a595c55f03239451cf0731f1d4fdf86f/examples/contour/03-envoy.yaml#L76-L79)

are you all adding your own liveness check? if so it would be interesting to see how that is configured and how that has worked out

given we only have a readiness check at the moment, if i'm understanding correctly we could just set that existing Listener to respect the global connection limit so that instances that are overloaded are taken out of the ready Service endpoints but not shut down

the admin/stats Listeners should always ignore the global limit and seems valid to have the readiness probe optionally respect the global connection Limit (or always respect it, given this will only matter if you actuall set a limit)@github-actions: The Contour project currently lacks enough contributors to adequately respond to all Issues.

This bot triages Issues according to the following rules:

- After 60d of inactivity, lifecycle/stale is applied
- After 30d of inactivity since lifecycle/stale was applied, the Issue is closed

You can:

- Mark this Issue as fresh by commenting
- Close this Issue
- Offer to help out with triage

Please send feedback to the #contour channel in the Kubernetes Slack@github-actions: The Contour project currently lacks enough contributors to adequately respond to all Issues.

This bot triages Issues according to the following rules:

- After 60d of inactivity, lifecycle/stale is applied
- After 30d of inactivity since lifecycle/stale was applied, the Issue is closed

You can:

- Mark this Issue as fresh by commenting
- Close this Issue
- Offer to help out with triage

Please send feedback to the #contour channel in the Kubernetes Slack@seth-epps: Reviving this because I got distracted and wasn't able to keep contributing to it.

> given we only have a readiness check at the moment, if i'm understanding correctly we could just set that existing Listener to respect the global connection limit so that instances that are overloaded are taken out of the ready Service endpoints but not shut down
>
> the admin/stats Listeners should always ignore the global limit and seems valid to have the readiness probe optionally respect the global connection Limit (or always respect it, given this will only matter if you actuall set a limit)

I think the way we have it running right now is the reverse; bypass the global connection limit on the default stats listeners and then configure a separate listener (`:8003`) that enforces the connection limit. This is done partly because it retains the existing behavior of the current stats listeners not enforcing the limits and to also keep metrics accessible by default. This is paired with overriding the deployment readiness checks so we end up with
```yaml
readinessProbe:
  # ...fields
  httpGet:
    path: /ready
    port: 8003 # enforces connection limit so pods are removed from endpoints
    scheme: HTTP
livenessProbe:
  # ...fields
  httpGet:
    path: /ready
    port: 8002 # does not enforce connection limit so pods stay alive until they can start serving traffic again
    scheme: HTTP
```

> are you all adding your own liveness check? if so it would be interesting to see how that is configured and how that has worked out

Right now we inject the listener configuration, but the only real difference is the readiness/liveness probes above (which is configured using the helm [`customReadinessProve`](https://github.com/bitnami/charts/blob/main/bitnami/contour/values.yaml#L226) to point at the listener enforcing the connection limits listening on`8003`

It's been working pretty great so far. We've observed the connection limits get hit in a few instances and this has self-recovered when it otherwise would have probably overwhelmed the resources.

~I'm working on cleaning up https://github.com/projectcontour/contour/compare/main...seth-epps:contour:globalconnections-overloadmanager and combining the changes needed for the listener configuration https://github.com/projectcontour/contour/compare/main...seth-epps:contour:options-listener-config~

@seth-epps: I've put together a proper change request now
https://github.com/projectcontour/contour/pull/6794

and also a proposed refactor to how we setup the stats listeners to make the configs a bit more ergonomic (IMO). I left it out of the core PR because it's a bit out of left-field and wasn't sure if it made sense in the larger context. There's no functional chnages
https://github.com/seth-epps/contour/pull/1

Solution patch:
diff --git a/apis/projectcontour/v1alpha1/contourconfig.go b/apis/projectcontour/v1alpha1/contourconfig.go
index 7019617a..0ff9651a 100644
--- a/apis/projectcontour/v1alpha1/contourconfig.go
+++ b/apis/projectcontour/v1alpha1/contourconfig.go
@@ -302,6 +302,16 @@ type EnvoyConfig struct {
 	// Network holds various configurable Envoy network values.
 	// +optional
 	Network *NetworkParameters `json:"network,omitempty"`
+
+	// OMEnforcedHealth defines the endpoint Envoy uses to serve health checks with
+	// the envoy overload manager actions, such as global connection limits, enforced.
+	//
+	// The configured values must be different from the endpoints
+	// configured by [EnvoyConfig.Metrics] and [EnvoyConfig.Health]
+	//
+	// This is disabled by default
+	// +optional
+	OMEnforcedHealth *HealthConfig `json:"omEnforcedHealth,omitempty"`
 }
 
 // DebugConfig contains Contour specific troubleshooting options.
diff --git a/apis/projectcontour/v1alpha1/contourconfig_helpers.go b/apis/projectcontour/v1alpha1/contourconfig_helpers.go
index a9f572a7..2c9b885b 100644
--- a/apis/projectcontour/v1alpha1/contourconfig_helpers.go
+++ b/apis/projectcontour/v1alpha1/contourconfig_helpers.go
@@ -112,6 +112,10 @@ func (e *EnvoyConfig) Validate() error {
 		return fmt.Errorf("invalid envoy configuration: %v", err)
 	}
 
+	if err := healthEndpointsInConflict(e.Metrics, e.Health, e.OMEnforcedHealth); err != nil {
+		return fmt.Errorf("invalid envoy configuration: %v", err)
+	}
+
 	if err := e.Logging.Validate(); err != nil {
 		return err
 	}
@@ -330,3 +334,17 @@ func endpointsInConfict(health *HealthConfig, metrics *MetricsConfig) error {
 	}
 	return nil
 }
+
+// healthEndpointsInConflict returns an error if the same address and port are used between the overload manager enforced health listener and metrics
+// _or_ the stats listener. Since the metrics would be validated against the stats listener already we only need to check that the overload manager
+// health listener is not in conflict with either metrics or stats
+func healthEndpointsInConflict(metrics *MetricsConfig, health, omEnforcedHealth *HealthConfig) error {
+	switch {
+	case omEnforcedHealth != nil && health != nil && omEnforcedHealth.Address == health.Address && omEnforcedHealth.Port == health.Port:
+		return fmt.Errorf("cannot use the same port for health checks and overload-manager enforced health checks")
+	case omEnforcedHealth != nil && metrics != nil && omEnforcedHealth.Address == metrics.Address && omEnforcedHealth.Port == metrics.Port:
+		return fmt.Errorf("cannot use the same port for metrics and overload-manager enforced health checks")
+	default:
+		return nil
+	}
+}
diff --git a/apis/projectcontour/v1alpha1/contourdeployment.go b/apis/projectcontour/v1alpha1/contourdeployment.go
index b430c2c1..16bd324f 100644
--- a/apis/projectcontour/v1alpha1/contourdeployment.go
+++ b/apis/projectcontour/v1alpha1/contourdeployment.go
@@ -245,6 +245,15 @@ type EnvoySettings struct {
 	//
 	// +optional
 	OverloadMaxHeapSize uint64 `json:"overloadMaxHeapSize,omitempty"`
+
+	// OverloadMaxDownstreamConn defines the envoy global downstream connection limit controlled by the overload manager.
+	// When the value is greater than 0 the overload manager is enabled and listeners
+	// will begin rejecting connections when the the connection threshold is hit.
+	// Metrics and health listeners are not subject to the connection limits, however,
+	// they still count against the global limit.
+	//
+	// +optional
+	OverloadMaxDownstreamConnections uint64 `json:"overloadMaxDownstreamConnections,omitempty"`
 }
 
 // WorkloadType is the type of Kubernetes workload to use for a component.
diff --git a/apis/projectcontour/v1alpha1/zz_generated.deepcopy.go b/apis/projectcontour/v1alpha1/zz_generated.deepcopy.go
index 5a016451..b0565dc5 100644
--- a/apis/projectcontour/v1alpha1/zz_generated.deepcopy.go
+++ b/apis/projectcontour/v1alpha1/zz_generated.deepcopy.go
@@ -572,6 +572,11 @@ func (in *EnvoyConfig) DeepCopyInto(out *EnvoyConfig) {
 		*out = new(NetworkParameters)
 		(*in).DeepCopyInto(*out)
 	}
+	if in.OMEnforcedHealth != nil {
+		in, out := &in.OMEnforcedHealth, &out.OMEnforcedHealth
+		*out = new(HealthConfig)
+		**out = **in
+	}
 }
 
 // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EnvoyConfig.
diff --git a/changelogs/unreleased/6794-seth-epps-minor.md b/changelogs/unreleased/6794-seth-epps-minor.md
new file mode 100644
index 00000000..7715c870
--- /dev/null
+++ b/changelogs/unreleased/6794-seth-epps-minor.md
@@ -0,0 +1,52 @@
+## Overload Manager - Max Global Connections
+
+Introduces an envoy bootstrap flag to enable the [global downstream connection limit overload manager resource monitors](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/resource_monitors/downstream_connections/v3/downstream_connections.proto#envoy-v3-api-msg-extensions-resource-monitors-downstream-connections-v3-downstreamconnectionsconfig).
+
+The new flag can be passed as an integer flag to the contour bootstrap subcommand, `overload-downstream-max-conn`.
+
+```sh
+contour bootstrap --help
+INFO[0000] maxprocs: Leaving GOMAXPROCS=10: CPU quota undefined
+usage: contour bootstrap [<flags>] <path>
+
+Generate bootstrap configuration.
+
+
+Flags:
+  -h, --[no-]help                Show context-sensitive help (also try --help-long and --help-man).
+      --log-format=text          Log output format for Contour. Either text or json.
+      --admin-address="/admin/admin.sock"
+                                 Path to Envoy admin unix domain socket.
+      --admin-port=ADMIN-PORT    DEPRECATED: Envoy admin interface port.
+      --dns-lookup-family=DNS-LOOKUP-FAMILY
+                                 Defines what DNS Resolution Policy to use for Envoy -> Contour cluster name lookup. Either v4, v6, auto, or all.
+      --envoy-cafile=ENVOY-CAFILE
+                                 CA Filename for Envoy secure xDS gRPC communication. ($ENVOY_CAFILE)
+      --envoy-cert-file=ENVOY-CERT-FILE
+                                 Client certificate filename for Envoy secure xDS gRPC communication. ($ENVOY_CERT_FILE)
+      --envoy-key-file=ENVOY-KEY-FILE
+                                 Client key filename for Envoy secure xDS gRPC communication. ($ENVOY_KEY_FILE)
+      --namespace="projectcontour"
+                                 The namespace the Envoy container will run in. ($CONTOUR_NAMESPACE)
+      --overload-downstream-max-conn=OVERLOAD-DOWNSTREAM-MAX-CONN
+                                 Defines the Envoy global downstream connection limit
+      --overload-max-heap=OVERLOAD-MAX-HEAP
+                                 Defines the maximum heap size in bytes until overload manager stops accepting new connections.
+      --resources-dir=RESOURCES-DIR
+                                 Directory where configuration files will be written to.
+      --xds-address=XDS-ADDRESS  xDS gRPC API address.
+      --xds-port=XDS-PORT        xDS gRPC API port.
+      --xds-resource-version="v3"
+                                 The versions of the xDS resources to request from Contour.
+
+Args:
+  <path>  Configuration file ('-' for standard output).
+```
+
+As part of this change, we also set the `ignore_global_conn_limit` flag to `true` on the existing admin listeners such
+that envoy remains live, ready, and serving stats even though it is rejecting downstream connections.
+
+To add some flexibility for health checks, in addition to adding a new bootstrap flag, there is a new configuration
+option for the envoy health config to enforce the envoy overload manager actions, namely rejecting requests. This
+"advanced" configuration gives the operator the ability to configure readiness and liveness to handle taking pods out
+of the pool of pods that can serve traffic.
diff --git a/cmd/contour/bootstrap.go b/cmd/contour/bootstrap.go
index dfa365f9..ccf8edcd 100644
--- a/cmd/contour/bootstrap.go
+++ b/cmd/contour/bootstrap.go
@@ -34,6 +34,7 @@ func registerBootstrap(app *kingpin.Application) (*kingpin.CmdClause, *envoy.Boo
 	bootstrap.Flag("envoy-cert-file", "Client certificate filename for Envoy secure xDS gRPC communication.").Envar("ENVOY_CERT_FILE").StringVar(&config.GrpcClientCert)
 	bootstrap.Flag("envoy-key-file", "Client key filename for Envoy secure xDS gRPC communication.").Envar("ENVOY_KEY_FILE").StringVar(&config.GrpcClientKey)
 	bootstrap.Flag("namespace", "The namespace the Envoy container will run in.").Envar("CONTOUR_NAMESPACE").Default("projectcontour").StringVar(&config.Namespace)
+	bootstrap.Flag("overload-downstream-max-conn", "Defines the Envoy global downstream connection limit.").Int64Var(&config.GlobalDownstreamConnectionLimit)
 	bootstrap.Flag("overload-max-heap", "Defines the maximum heap size in bytes until overload manager stops accepting new connections.").Uint64Var(&config.MaximumHeapSizeBytes)
 	bootstrap.Flag("resources-dir", "Directory where configuration files will be written to.").StringVar(&config.ResourcesDir)
 	bootstrap.Flag("xds-address", "xDS gRPC API address.").StringVar(&config.XDSAddress)
diff --git a/cmd/contour/contour.go b/cmd/contour/contour.go
index 8fb99cfd..a5989b97 100644
--- a/cmd/contour/contour.go
+++ b/cmd/contour/contour.go
@@ -104,6 +104,9 @@ func main() {
 		if err := envoy.ValidAdminAddress(bootstrapCtx.AdminAddress); err != nil {
 			log.WithField("flag", "--admin-address").WithError(err).Fatal("failed to parse bootstrap args")
 		}
+		if err := envoy.ValidConnectionLimit(bootstrapCtx.GlobalDownstreamConnectionLimit); err != nil {
+			log.WithField("flag", "--overload-downstream-max-conn").WithError(err).Fatal("failed to parse bootstrap args")
+		}
 		envoyGen := envoy_v3.NewEnvoyGen(envoy_v3.EnvoyGenOpt{
 			XDSClusterName: envoy_v3.DefaultXDSClusterName,
 		})
diff --git a/cmd/contour/serve.go b/cmd/contour/serve.go
index e2110cc3..72831bac 100644
--- a/cmd/contour/serve.go
+++ b/cmd/contour/serve.go
@@ -501,7 +501,7 @@ func (s *Server) doServe() error {
 	})
 
 	resources := []xdscache.ResourceCache{
-		xdscache_v3.NewListenerCache(listenerConfig, *contourConfiguration.Envoy.Metrics, *contourConfiguration.Envoy.Health, *contourConfiguration.Envoy.Network.EnvoyAdminPort, envoyGen),
+		xdscache_v3.NewListenerCache(listenerConfig, *contourConfiguration.Envoy.Metrics, *contourConfiguration.Envoy.Health, contourConfiguration.Envoy.OMEnforcedHealth, *contourConfiguration.Envoy.Network.EnvoyAdminPort, envoyGen),
 		xdscache_v3.NewSecretsCache(envoy_v3.StatsSecrets(contourConfiguration.Envoy.Metrics.TLS)),
 		&xdscache_v3.RouteCache{},
 		xdscache_v3.NewClusterCache(envoyGen),
diff --git a/cmd/contour/servecontext.go b/cmd/contour/servecontext.go
index 5d9095fc..59db754c 100644
--- a/cmd/contour/servecontext.go
+++ b/cmd/contour/servecontext.go
@@ -515,6 +515,14 @@ func (ctx *serveContext) convertToContourConfigurationSpec() contour_v1alpha1.Co
 		Port:    ctx.statsPort,
 	}
 
+	var envoyOMEnforcedHealthListenerConfig *contour_v1alpha1.HealthConfig
+	if ctx.Config.OMEnforcedHealthListener != nil {
+		envoyOMEnforcedHealthListenerConfig = &contour_v1alpha1.HealthConfig{
+			Address: ctx.Config.OMEnforcedHealthListener.Address,
+			Port:    ctx.Config.OMEnforcedHealthListener.Port,
+		}
+	}
+
 	// Override metrics endpoint info from config files
 	//
 	// Note!
@@ -603,6 +611,7 @@ func (ctx *serveContext) convertToContourConfigurationSpec() contour_v1alpha1.Co
 				EnvoyAdminPort:            &ctx.Config.Network.EnvoyAdminPort,
 				EnvoyStripTrailingHostDot: &ctx.Config.Network.EnvoyStripTrailingHostDot,
 			},
+			OMEnforcedHealth: envoyOMEnforcedHealthListenerConfig,
 		},
 		Gateway: gatewayConfig,
 		HTTPProxy: &contour_v1alpha1.HTTPProxyConfig{
diff --git a/examples/contour/01-contour-config.yaml b/examples/contour/01-contour-config.yaml
index a8c7c3fe..9df6c608 100644
--- a/examples/contour/01-contour-config.yaml
+++ b/examples/contour/01-contour-config.yaml
@@ -179,3 +179,7 @@ data:
     #  socket-options:
     #    tos: 64
     #    traffic-class: 64
+    #
+    # omEnforcedHealthListener:
+    #   address: 0.0.0.0
+    #   port: 8003
diff --git a/examples/contour/01-crds.yaml b/examples/contour/01-crds.yaml
index b1a280bd..c3b216e5 100644
--- a/examples/contour/01-crds.yaml
+++ b/examples/contour/01-crds.yaml
@@ -549,6 +549,22 @@ spec:
                           Contour's default is false.
                         type: boolean
                     type: object
+                  omEnforcedHealth:
+                    description: |-
+                      OMEnforcedHealth defines the endpoint Envoy uses to serve health checks with
+                      the envoy overload manager actions, such as global connection limits, enforced.
+                      The configured values must be different from the endpoints
+                      configured by [EnvoyConfig.Metrics] and [EnvoyConfig.Health]
+                      This is disabled by default
+                    properties:
+                      address:
+                        description: Defines the health address interface.
+                        minLength: 1
+                        type: string
+                      port:
+                        description: Defines the health port.
+                        type: integer
+                    type: object
                   service:
                     description: |-
                       Service holds Envoy service parameters for setting Ingress status.
@@ -3781,6 +3797,15 @@ spec:
                           type: object
                         type: array
                     type: object
+                  overloadMaxDownstreamConnections:
+                    description: |-
+                      OverloadMaxDownstreamConn defines the envoy global downstream connection limit controlled by the overload manager.
+                      When the value is greater than 0 the overload manager is enabled and listeners
+                      will begin rejecting connections when the the connection threshold is hit.
+                      Metrics and health listeners are not subject to the connection limits, however,
+                      they still count against the global limit.
+                    format: int64
+                    type: integer
                   overloadMaxHeapSize:
                     description: |-
                       OverloadMaxHeapSize defines the maximum heap memory of the envoy controlled by the overload manager.
@@ -4392,6 +4417,22 @@ spec:
                               Contour's default is false.
                             type: boolean
                         type: object
+                      omEnforcedHealth:
+                        description: |-
+                          OMEnforcedHealth defines the endpoint Envoy uses to serve health checks with
+                          the envoy overload manager actions, such as global connection limits, enforced.
+                          The configured values must be different from the endpoints
+                          configured by [EnvoyConfig.Metrics] and [EnvoyConfig.Health]
+                          This is disabled by default
+                        properties:
+                          address:
+                            description: Defines the health address interface.
+                            minLength: 1
+                            type: string
+                          port:
+                            description: Defines the health port.
+                            type: integer
+                        type: object
                       service:
                         description: |-
                           Service holds Envoy service parameters for setting Ingress status.
diff --git a/examples/render/contour-deployment.yaml b/examples/render/contour-deployment.yaml
index 36b16ded..9495f46d 100644
--- a/examples/render/contour-deployment.yaml
+++ b/examples/render/contour-deployment.yaml
@@ -212,6 +212,10 @@ data:
     #  socket-options:
     #    tos: 64
     #    traffic-class: 64
+    #
+    # omEnforcedHealthListener:
+    #   address: 0.0.0.0
+    #   port: 8003
 
 ---
 apiVersion: apiextensions.k8s.io/v1
@@ -764,6 +768,22 @@ spec:
                           Contour's default is false.
                         type: boolean
                     type: object
+                  omEnforcedHealth:
+                    description: |-
+                      OMEnforcedHealth defines the endpoint Envoy uses to serve health checks with
+                      the envoy overload manager actions, such as global connection limits, enforced.
+                      The configured values must be different from the endpoints
+                      configured by [EnvoyConfig.Metrics] and [EnvoyConfig.Health]
+                      This is disabled by default
+                    properties:
+                      address:
+                        description: Defines the health address interface.
+                        minLength: 1
+                        type: string
+                      port:
+                        description: Defines the health port.
+                        type: integer
+                    type: object
                   service:
                     description: |-
                       Service holds Envoy service parameters for setting Ingress status.
@@ -3996,6 +4016,15 @@ spec:
                           type: object
                         type: array
                     type: object
+                  overloadMaxDownstreamConnections:
+                    description: |-
+                      OverloadMaxDownstreamConn defines the envoy global downstream connection limit controlled by the overload manager.
+                      When the value is greater than 0 the overload manager is enabled and listeners
+                      will begin rejecting connections when the the connection threshold is hit.
+                      Metrics and health listeners are not subject to the connection limits, however,
+                      they still count against the global limit.
+                    format: int64
+                    type: integer
                   overloadMaxHeapSize:
                     description: |-
                       OverloadMaxHeapSize defines the maximum heap memory of the envoy controlled by the overload manager.
@@ -4607,6 +4636,22 @@ spec:
                               Contour's default is false.
                             type: boolean
                         type: object
+                      omEnforcedHealth:
+                        description: |-
+                          OMEnforcedHealth defines the endpoint Envoy uses to serve health checks with
+                          the envoy overload manager actions, such as global connection limits, enforced.
+                          The configured values must be different from the endpoints
+                          configured by [EnvoyConfig.Metrics] and [EnvoyConfig.Health]
+                          This is disabled by default
+                        properties:
+                          address:
+                            description: Defines the health address interface.
+                            minLength: 1
+                            type: string
+                          port:
+                            description: Defines the health port.
+                            type: integer
+                        type: object
                       service:
                         description: |-
                           Service holds Envoy service parameters for setting Ingress status.
diff --git a/examples/render/contour-gateway-provisioner.yaml b/examples/render/contour-gateway-provisioner.yaml
index ba469e61..962656e4 100644
--- a/examples/render/contour-gateway-provisioner.yaml
+++ b/examples/render/contour-gateway-provisioner.yaml
@@ -560,6 +560,22 @@ spec:
                           Contour's default is false.
                         type: boolean
                     type: object
+                  omEnforcedHealth:
+                    description: |-
+                      OMEnforcedHealth defines the endpoint Envoy uses to serve health checks with
+                      the envoy overload manager actions, such as global connection limits, enforced.
+                      The configured values must be different from the endpoints
+                      configured by [EnvoyConfig.Metrics] and [EnvoyConfig.Health]
+                      This is disabled by default
+                    properties:
+                      address:
+                        description: Defines the health address interface.
+                        minLength: 1
+                        type: string
+                      port:
+                        description: Defines the health port.
+                        type: integer
+                    type: object
                   service:
                     description: |-
                       Service holds Envoy service parameters for setting Ingress status.
@@ -3792,6 +3808,15 @@ spec:
                           type: object
                         type: array
                     type: object
+                  overloadMaxDownstreamConnections:
+                    description: |-
+                      OverloadMaxDownstreamConn defines the envoy global downstream connection limit controlled by the overload manager.
+                      When the value is greater than 0 the overload manager is enabled and listeners
+                      will begin rejecting connections when the the connection threshold is hit.
+                      Metrics and health listeners are not subject to the connection limits, however,
+                      they still count against the global limit.
+                    format: int64
+                    type: integer
                   overloadMaxHeapSize:
                     description: |-
                       OverloadMaxHeapSize defines the maximum heap memory of the envoy controlled by the overload manager.
@@ -4403,6 +4428,22 @@ spec:
                               Contour's default is false.
                             type: boolean
                         type: object
+                      omEnforcedHealth:
+                        description: |-
+                          OMEnforcedHealth defines the endpoint Envoy uses to serve health checks with
+                          the envoy overload manager actions, such as global connection limits, enforced.
+                          The configured values must be different from the endpoints
+                          configured by [EnvoyConfig.Metrics] and [EnvoyConfig.Health]
+                          This is disabled by default
+                        properties:
+                          address:
+                            description: Defines the health address interface.
+                            minLength: 1
+                            type: string
+                          port:
+                            description: Defines the health port.
+                            type: integer
+                        type: object
                       service:
                         description: |-
                           Service holds Envoy service parameters for setting Ingress status.
diff --git a/examples/render/contour-gateway.yaml b/examples/render/contour-gateway.yaml
index 85b49baa..0ea5b266 100644
--- a/examples/render/contour-gateway.yaml
+++ b/examples/render/contour-gateway.yaml
@@ -585,6 +585,22 @@ spec:
                           Contour's default is false.
                         type: boolean
                     type: object
+                  omEnforcedHealth:
+                    description: |-
+                      OMEnforcedHealth defines the endpoint Envoy uses to serve health checks with
+                      the envoy overload manager actions, such as global connection limits, enforced.
+                      The configured values must be different from the endpoints
+                      configured by [EnvoyConfig.Metrics] and [EnvoyConfig.Health]
+                      This is disabled by default
+                    properties:
+                      address:
+                        description: Defines the health address interface.
+                        minLength: 1
+                        type: string
+                      port:
+                        description: Defines the health port.
+                        type: integer
+                    type: object
                   service:
                     description: |-
                       Service holds Envoy service parameters for setting Ingress status.
@@ -3817,6 +3833,15 @@ spec:
                           type: object
                         type: array
                     type: object
+                  overloadMaxDownstreamConnections:
+                    description: |-
+                      OverloadMaxDownstreamConn defines the envoy global downstream connection limit controlled by the overload manager.
+                      When the value is greater than 0 the overload manager is enabled and listeners
+                      will begin rejecting connections when the the connection threshold is hit.
+                      Metrics and health listeners are not subject to the connection limits, however,
+                      they still count against the global limit.
+                    format: int64
+                    type: integer
                   overloadMaxHeapSize:
                     description: |-
                       OverloadMaxHeapSize defines the maximum heap memory of the envoy controlled by the overload manager.
@@ -4428,6 +4453,22 @@ spec:
                               Contour's default is false.
                             type: boolean
                         type: object
+                      omEnforcedHealth:
+                        description: |-
+                          OMEnforcedHealth defines the endpoint Envoy uses to serve health checks with
+                          the envoy overload manager actions, such as global connection limits, enforced.
+                          The configured values must be different from the endpoints
+                          configured by [EnvoyConfig.Metrics] and [EnvoyConfig.Health]
+                          This is disabled by default
+                        properties:
+                          address:
+                            description: Defines the health address interface.
+                            minLength: 1
+                            type: string
+                          port:
+                            description: Defines the health port.
+                            type: integer
+                        type: object
                       service:
                         description: |-
                           Service holds Envoy service parameters for setting Ingress status.
diff --git a/examples/render/contour.yaml b/examples/render/contour.yaml
index 93497303..1b3c1b8d 100644
--- a/examples/render/contour.yaml
+++ b/examples/render/contour.yaml
@@ -212,6 +212,10 @@ data:
     #  socket-options:
     #    tos: 64
     #    traffic-class: 64
+    #
+    # omEnforcedHealthListener:
+    #   address: 0.0.0.0
+    #   port: 8003
 
 ---
 apiVersion: apiextensions.k8s.io/v1
@@ -764,6 +768,22 @@ spec:
                           Contour's default is false.
                         type: boolean
                     type: object
+                  omEnforcedHealth:
+                    description: |-
+                      OMEnforcedHealth defines the endpoint Envoy uses to serve health checks with
+                      the envoy overload manager actions, such as global connection limits, enforced.
+                      The configured values must be different from the endpoints
+                      configured by [EnvoyConfig.Metrics] and [EnvoyConfig.Health]
+                      This is disabled by default
+                    properties:
+                      address:
+                        description: Defines the health address interface.
+                        minLength: 1
+                        type: string
+                      port:
+                        description: Defines the health port.
+                        type: integer
+                    type: object
                   service:
                     description: |-
                       Service holds Envoy service parameters for setting Ingress status.
@@ -3996,6 +4016,15 @@ spec:
                           type: object
                         type: array
                     type: object
+                  overloadMaxDownstreamConnections:
+                    description: |-
+                      OverloadMaxDownstreamConn defines the envoy global downstream connection limit controlled by the overload manager.
+                      When the value is greater than 0 the overload manager is enabled and listeners
+                      will begin rejecting connections when the the connection threshold is hit.
+                      Metrics and health listeners are not subject to the connection limits, however,
+                      they still count against the global limit.
+                    format: int64
+                    type: integer
                   overloadMaxHeapSize:
                     description: |-
                       OverloadMaxHeapSize defines the maximum heap memory of the envoy controlled by the overload manager.
@@ -4607,6 +4636,22 @@ spec:
                               Contour's default is false.
                             type: boolean
                         type: object
+                      omEnforcedHealth:
+                        description: |-
+                          OMEnforcedHealth defines the endpoint Envoy uses to serve health checks with
+                          the envoy overload manager actions, such as global connection limits, enforced.
+                          The configured values must be different from the endpoints
+                          configured by [EnvoyConfig.Metrics] and [EnvoyConfig.Health]
+                          This is disabled by default
+                        properties:
+                          address:
+                            description: Defines the health address interface.
+                            minLength: 1
+                            type: string
+                          port:
+                            description: Defines the health port.
+                            type: integer
+                        type: object
                       service:
                         description: |-
                           Service holds Envoy service parameters for setting Ingress status.
diff --git a/internal/envoy/bootstrap.go b/internal/envoy/bootstrap.go
index c268c0fd..e1b6c84e 100644
--- a/internal/envoy/bootstrap.go
+++ b/internal/envoy/bootstrap.go
@@ -95,6 +95,12 @@ type BootstrapConfig struct {
 	// MaximumHeapSizeBytes specifies the number of bytes that overload manager allows heap to grow to.
 	// When reaching the set threshold, new connections are denied.
 	MaximumHeapSizeBytes uint64
+
+	// GlobalDownstreamConnectionLimit specifies the maximum number of global open downstream connections to envoy.
+	// When at the limit, envoy will reject connections at L4.
+	//
+	// Although a valid limit must be >= 0, to avoid overflow we require the type be int64
+	GlobalDownstreamConnectionLimit int64
 }
 
 // GetXdsAddress returns the address configured or defaults to "127.0.0.1"
@@ -130,6 +136,16 @@ func ValidAdminAddress(address string) error {
 	return nil
 }
 
+// ValidConnectionLimit checks if the supplied
+// envoy global connection limit is an integer
+// greater than or equal to 0.
+func ValidConnectionLimit(limit int64) error {
+	if limit < 0 {
+		return fmt.Errorf("invalid value %d, cannot be < 0", limit)
+	}
+	return nil
+}
+
 func stringOrDefault(s, def string) string {
 	if s == "" {
 		return def
diff --git a/internal/envoy/v3/bootstrap.go b/internal/envoy/v3/bootstrap.go
index 41b50337..910842fa 100644
--- a/internal/envoy/v3/bootstrap.go
+++ b/internal/envoy/v3/bootstrap.go
@@ -32,6 +32,7 @@ import (
 	envoy_config_overload_v3 "github.com/envoyproxy/go-control-plane/envoy/config/overload/v3"
 	envoy_access_logger_file_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/access_loggers/file/v3"
 	envoy_regex_engines_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/regex_engines/v3"
+	envoy_downstream_connections_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/resource_monitors/downstream_connections/v3"
 	envoy_fixed_heap_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/resource_monitors/fixed_heap/v3"
 	envoy_transport_socket_tls_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tls/v3"
 	envoy_service_discovery_v3 "github.com/envoyproxy/go-control-plane/envoy/service/discovery/v3"
@@ -252,50 +253,14 @@ func (e *EnvoyGen) bootstrapConfig(c *envoy.BootstrapConfig) *envoy_config_boots
 			Address:   unixSocketAddress(c.GetAdminAddress()),
 		},
 	}
-	if c.MaximumHeapSizeBytes > 0 {
+	if c.MaximumHeapSizeBytes > 0 || c.GlobalDownstreamConnectionLimit > 0 {
 		bootstrap.OverloadManager = &envoy_config_overload_v3.OverloadManager{
 			RefreshInterval: durationpb.New(250 * time.Millisecond),
-			ResourceMonitors: []*envoy_config_overload_v3.ResourceMonitor{
-				{
-					Name: "envoy.resource_monitors.fixed_heap",
-					ConfigType: &envoy_config_overload_v3.ResourceMonitor_TypedConfig{
-						TypedConfig: protobuf.MustMarshalAny(
-							&envoy_fixed_heap_v3.FixedHeapConfig{
-								MaxHeapSizeBytes: c.MaximumHeapSizeBytes,
-							}),
-					},
-				},
-			},
-			Actions: []*envoy_config_overload_v3.OverloadAction{
-				{
-					Name: "envoy.overload_actions.shrink_heap",
-					Triggers: []*envoy_config_overload_v3.Trigger{
-						{
-							Name: "envoy.resource_monitors.fixed_heap",
-							TriggerOneof: &envoy_config_overload_v3.Trigger_Threshold{
-								Threshold: &envoy_config_overload_v3.ThresholdTrigger{
-									Value: 0.95,
-								},
-							},
-						},
-					},
-				},
-				{
-					Name: "envoy.overload_actions.stop_accepting_requests",
-					Triggers: []*envoy_config_overload_v3.Trigger{
-						{
-							Name: "envoy.resource_monitors.fixed_heap",
-							TriggerOneof: &envoy_config_overload_v3.Trigger_Threshold{
-								Threshold: &envoy_config_overload_v3.ThresholdTrigger{
-									Value: 0.98,
-								},
-							},
-						},
-					},
-				},
-			},
 		}
+		includeMaxHeapMonitoring(bootstrap, c.MaximumHeapSizeBytes)
+		includeMaxConnectionMonitoring(bootstrap, c.GlobalDownstreamConnectionLimit)
 	}
+
 	return bootstrap
 }
 
@@ -461,3 +426,68 @@ func validationContextSdsSecretConfig(c *envoy.BootstrapConfig) *envoy_service_d
 		Resources: []*anypb.Any{protobuf.MustMarshalAny(secret)},
 	}
 }
+
+// includeMaxHeapMonitoring appends the fixed heap resource monitor and corresponding
+// overload actions to the overload manager
+func includeMaxHeapMonitoring(bootstrap *envoy_config_bootstrap_v3.Bootstrap, maxHeapBytes uint64) {
+	if maxHeapBytes > 0 {
+		bootstrap.OverloadManager.ResourceMonitors = append(bootstrap.OverloadManager.ResourceMonitors,
+			&envoy_config_overload_v3.ResourceMonitor{
+				Name: "envoy.resource_monitors.fixed_heap",
+				ConfigType: &envoy_config_overload_v3.ResourceMonitor_TypedConfig{
+					TypedConfig: protobuf.MustMarshalAny(
+						&envoy_fixed_heap_v3.FixedHeapConfig{
+							MaxHeapSizeBytes: maxHeapBytes,
+						}),
+				},
+			},
+		)
+
+		bootstrap.OverloadManager.Actions = append(bootstrap.OverloadManager.Actions,
+			&envoy_config_overload_v3.OverloadAction{
+				Name: "envoy.overload_actions.shrink_heap",
+				Triggers: []*envoy_config_overload_v3.Trigger{
+					{
+						Name: "envoy.resource_monitors.fixed_heap",
+						TriggerOneof: &envoy_config_overload_v3.Trigger_Threshold{
+							Threshold: &envoy_config_overload_v3.ThresholdTrigger{
+								Value: 0.95,
+							},
+						},
+					},
+				},
+			},
+			&envoy_config_overload_v3.OverloadAction{
+				Name: "envoy.overload_actions.stop_accepting_requests",
+				Triggers: []*envoy_config_overload_v3.Trigger{
+					{
+						Name: "envoy.resource_monitors.fixed_heap",
+						TriggerOneof: &envoy_config_overload_v3.Trigger_Threshold{
+							Threshold: &envoy_config_overload_v3.ThresholdTrigger{
+								Value: 0.98,
+							},
+						},
+					},
+				},
+			},
+		)
+	}
+}
+
+// includeMaxConnectionMonitoring appends the downstream connection resource monitor to
+// the overload manager
+func includeMaxConnectionMonitoring(bootstrap *envoy_config_bootstrap_v3.Bootstrap, maxConns int64) {
+	if maxConns > 0 {
+		bootstrap.OverloadManager.ResourceMonitors = append(bootstrap.OverloadManager.ResourceMonitors,
+			&envoy_config_overload_v3.ResourceMonitor{
+				Name: "envoy.resource_monitors.global_downstream_max_connections",
+				ConfigType: &envoy_config_overload_v3.ResourceMonitor_TypedConfig{
+					TypedConfig: protobuf.MustMarshalAny(
+						&envoy_downstream_connections_v3.DownstreamConnectionsConfig{
+							MaxActiveDownstreamConnections: maxConns,
+						}),
+				},
+			},
+		)
+	}
+}
diff --git a/internal/envoy/v3/stats.go b/internal/envoy/v3/stats.go
index 7842d57d..a3b06eeb 100644
--- a/internal/envoy/v3/stats.go
+++ b/internal/envoy/v3/stats.go
@@ -38,7 +38,7 @@ const (
 // The listeners are configured to serve:
 //   - prometheus metrics on /stats (either over HTTP or HTTPS)
 //   - readiness probe on /ready (always over HTTP)
-func (e *EnvoyGen) StatsListeners(metrics contour_v1alpha1.MetricsConfig, health contour_v1alpha1.HealthConfig) []*envoy_config_listener_v3.Listener {
+func (e *EnvoyGen) StatsListeners(metrics contour_v1alpha1.MetricsConfig, health contour_v1alpha1.HealthConfig, omEnforcedHealth *contour_v1alpha1.HealthConfig) []*envoy_config_listener_v3.Listener {
 	var listeners []*envoy_config_listener_v3.Listener
 
 	switch {
@@ -51,11 +51,13 @@ func (e *EnvoyGen) StatsListeners(metrics contour_v1alpha1.MetricsConfig, health
 			FilterChains: filterChain("stats",
 				DownstreamTLSTransportSocket(
 					e.downstreamTLSContext(metrics.TLS.CAFile != "")), routeForAdminInterface("/stats", "/stats/prometheus")),
+			IgnoreGlobalConnLimit: true,
 		}, {
-			Name:          "health",
-			Address:       SocketAddress(health.Address, health.Port),
-			SocketOptions: NewSocketOptions().TCPKeepalive().Build(),
-			FilterChains:  filterChain("stats", nil, routeForAdminInterface("/ready")),
+			Name:                  "health",
+			Address:               SocketAddress(health.Address, health.Port),
+			SocketOptions:         NewSocketOptions().TCPKeepalive().Build(),
+			FilterChains:          filterChain("stats", nil, routeForAdminInterface("/ready")),
+			IgnoreGlobalConnLimit: true,
 		}}
 
 	// Create combined HTTP listener for metrics and health.
@@ -70,23 +72,36 @@ func (e *EnvoyGen) StatsListeners(metrics contour_v1alpha1.MetricsConfig, health
 				"/stats",
 				"/stats/prometheus",
 			)),
+			IgnoreGlobalConnLimit: true,
 		}}
 
 	// Create separate HTTP listeners for metrics and health.
 	default:
 		listeners = []*envoy_config_listener_v3.Listener{{
-			Name:          "stats",
-			Address:       SocketAddress(metrics.Address, metrics.Port),
-			SocketOptions: NewSocketOptions().TCPKeepalive().Build(),
-			FilterChains:  filterChain("stats", nil, routeForAdminInterface("/stats", "/stats/prometheus")),
+			Name:                  "stats",
+			Address:               SocketAddress(metrics.Address, metrics.Port),
+			SocketOptions:         NewSocketOptions().TCPKeepalive().Build(),
+			FilterChains:          filterChain("stats", nil, routeForAdminInterface("/stats", "/stats/prometheus")),
+			IgnoreGlobalConnLimit: true,
 		}, {
-			Name:          "health",
-			Address:       SocketAddress(health.Address, health.Port),
-			SocketOptions: NewSocketOptions().TCPKeepalive().Build(),
-			FilterChains:  filterChain("stats", nil, routeForAdminInterface("/ready")),
+			Name:                  "health",
+			Address:               SocketAddress(health.Address, health.Port),
+			SocketOptions:         NewSocketOptions().TCPKeepalive().Build(),
+			FilterChains:          filterChain("stats", nil, routeForAdminInterface("/ready")),
+			IgnoreGlobalConnLimit: true,
 		}}
 	}
 
+	if omEnforcedHealth != nil {
+		listeners = append(listeners, &envoy_config_listener_v3.Listener{
+			Name:                  "health-om-enforced",
+			Address:               SocketAddress(omEnforcedHealth.Address, omEnforcedHealth.Port),
+			SocketOptions:         NewSocketOptions().TCPKeepalive().Build(),
+			FilterChains:          filterChain("stats", nil, routeForAdminInterface("/ready")),
+			IgnoreGlobalConnLimit: false,
+		})
+	}
+
 	return listeners
 }
 
@@ -111,7 +126,8 @@ func AdminListener(port int) *envoy_config_listener_v3.Listener {
 				"/stats/recentlookups",
 			),
 		),
-		SocketOptions: NewSocketOptions().TCPKeepalive().Build(),
+		SocketOptions:         NewSocketOptions().TCPKeepalive().Build(),
+		IgnoreGlobalConnLimit: true,
 	}
 }
 
diff --git a/internal/provisioner/controller/gateway.go b/internal/provisioner/controller/gateway.go
index b1daaf11..96c14c69 100644
--- a/internal/provisioner/controller/gateway.go
+++ b/internal/provisioner/controller/gateway.go
@@ -360,6 +360,10 @@ func (r *gatewayReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct
 				contourModel.Spec.EnvoyMaxHeapSizeBytes = envoyParams.OverloadMaxHeapSize
 			}
 
+			if envoyParams.OverloadMaxDownstreamConnections > 0 {
+				contourModel.Spec.EnvoyMaxDownstreamConnections = envoyParams.OverloadMaxDownstreamConnections
+			}
+
 		}
 	}
 
diff --git a/internal/provisioner/model/model.go b/internal/provisioner/model/model.go
index 9272dee1..ad60c254 100644
--- a/internal/provisioner/model/model.go
+++ b/internal/provisioner/model/model.go
@@ -43,12 +43,13 @@ func Default(namespace, name string) *Contour {
 			Name:      name,
 		},
 		Spec: ContourSpec{
-			ContourReplicas:       2,
-			EnvoyWorkloadType:     WorkloadTypeDaemonSet,
-			EnvoyReplicas:         2, // ignored if not provisioning Envoy as a deployment.
-			EnvoyLogLevel:         contour_v1alpha1.InfoLog,
-			EnvoyBaseID:           0,
-			EnvoyMaxHeapSizeBytes: 0,
+			ContourReplicas:               2,
+			EnvoyWorkloadType:             WorkloadTypeDaemonSet,
+			EnvoyReplicas:                 2, // ignored if not provisioning Envoy as a deployment.
+			EnvoyLogLevel:                 contour_v1alpha1.InfoLog,
+			EnvoyBaseID:                   0,
+			EnvoyMaxHeapSizeBytes:         0,
+			EnvoyMaxDownstreamConnections: 0,
 			NetworkPublishing: NetworkPublishing{
 				Envoy: EnvoyNetworkPublishing{
 					Type:                  LoadBalancerServicePublishingType,
@@ -244,11 +245,15 @@ type ContourSpec struct {
 	// defaults to 0.
 	EnvoyBaseID int32
 
-	// MaximumHeapSizeBytes defines how much memory the overload manager controls Envoy to allocate at most.
-	// If the value is 0, the overload manager is disabled.
+	// EnvoyMaxHeapSizeBytes defines how much memory the overload manager controls Envoy to allocate at most.
 	// defaults to 0.
 	EnvoyMaxHeapSizeBytes uint64
 
+	// EnvoyMaxDownstreamConnections defines the global downstream connection limit before
+	// listeners begin rejecting connections.
+	// defaults to 0.
+	EnvoyMaxDownstreamConnections uint64
+
 	// WatchNamespaces is an array of namespaces. Setting it will instruct the contour instance
 	// to only watch these set of namespaces
 	// default is nil, contour will watch resource of all namespaces
diff --git a/internal/provisioner/objects/dataplane/dataplane.go b/internal/provisioner/objects/dataplane/dataplane.go
index c5d43644..5246e6cf 100644
--- a/internal/provisioner/objects/dataplane/dataplane.go
+++ b/internal/provisioner/objects/dataplane/dataplane.go
@@ -294,6 +294,7 @@ func desiredContainers(contour *model.Contour, contourImage, envoyImage string)
 				fmt.Sprintf("--envoy-cert-file=%s", filepath.Join("/", envoyCertsVolMntDir, "tls.crt")),
 				fmt.Sprintf("--envoy-key-file=%s", filepath.Join("/", envoyCertsVolMntDir, "tls.key")),
 				fmt.Sprintf("--overload-max-heap=%d", contour.Spec.EnvoyMaxHeapSizeBytes),
+				fmt.Sprintf("--overload-downstream-max-conn=%d", contour.Spec.EnvoyMaxDownstreamConnections),
 			},
 			VolumeMounts: []core_v1.VolumeMount{
 				{
diff --git a/internal/xdscache/v3/listener.go b/internal/xdscache/v3/listener.go
index 7bc25621..9fc3ad94 100644
--- a/internal/xdscache/v3/listener.go
+++ b/internal/xdscache/v3/listener.go
@@ -296,6 +296,7 @@ func NewListenerCache(
 	listenerConfig ListenerConfig,
 	metricsConfig contour_v1alpha1.MetricsConfig,
 	healthConfig contour_v1alpha1.HealthConfig,
+	omEnforcedHealthConfig *contour_v1alpha1.HealthConfig,
 	adminPort int,
 	envoyGen *envoy_v3.EnvoyGen,
 ) *ListenerCache {
@@ -305,7 +306,7 @@ func NewListenerCache(
 		envoyGen:     envoyGen,
 	}
 
-	for _, l := range envoyGen.StatsListeners(metricsConfig, healthConfig) {
+	for _, l := range envoyGen.StatsListeners(metricsConfig, healthConfig, omEnforcedHealthConfig) {
 		listenerCache.staticValues[l.Name] = l
 	}
 
diff --git a/pkg/config/parameters.go b/pkg/config/parameters.go
index ce9149a9..65f211e2 100644
--- a/pkg/config/parameters.go
+++ b/pkg/config/parameters.go
@@ -704,6 +704,15 @@ type Parameters struct {
 	// from k8s endpoint slices. defaults to true,
 	// if false then reading endpoint data from the k8s endpoints.
 	FeatureFlags []string `yaml:"featureFlags,omitempty"`
+
+	// OMEnforcedHealthListener holds configuration for an envoy listener
+	// that enforces the overload manager actions, like global downstream
+	// connection limits.
+	//
+	// The configured values must be different from the endpoints
+	// configured by [Parameters.Metrics.Envoy] or any listeners
+	// configured by [contour_v1alpha1.ContourConfigurationSpec.Envoy]
+	OMEnforcedHealthListener *OMEnforcedHealthListenerConfig `yaml:"omEnforcedHealthListener,omitempty"`
 }
 
 // Tracing defines properties for exporting trace data to OpenTelemetry.
@@ -875,6 +884,14 @@ type MetricsServerParameters struct {
 // to toggle new contour features.
 type FeatureFlags []string
 
+type OMEnforcedHealthListenerConfig struct {
+	// Address that the listener will bind to
+	Address string `yaml:"address,omitempty"`
+
+	// Port that the listener will bind to.
+	Port int `yaml:"port,omitempty"`
+}
+
 func (p *MetricsParameters) Validate() error {
 	if err := p.Contour.Validate(); err != nil {
 		return fmt.Errorf("metrics.contour: %v", err)
diff --git a/site/content/docs/main/config/api-reference.html b/site/content/docs/main/config/api-reference.html
index 76cad6d8..9cd66486 100644
--- a/site/content/docs/main/config/api-reference.html
+++ b/site/content/docs/main/config/api-reference.html
@@ -6884,6 +6884,25 @@ NetworkParameters
 <p>Network holds various configurable Envoy network values.</p>
 </td>
 </tr>
+<tr>
+<td style="white-space:nowrap">
+<code>omEnforcedHealth</code>
+<br>
+<em>
+<a href="#projectcontour.io/v1alpha1.HealthConfig">
+HealthConfig
+</a>
+</em>
+</td>
+<td>
+<em>(Optional)</em>
+<p>OMEnforcedHealth defines the endpoint Envoy uses to serve health checks with
+the envoy overload manager actions, such as global connection limits, enforced.</p>
+<p>The configured values must be different from the endpoints
+configured by [EnvoyConfig.Metrics] and [EnvoyConfig.Health]</p>
+<p>This is disabled by default</p>
+</td>
+</tr>
 </tbody>
 </table>
 <h3 id="projectcontour.io/v1alpha1.EnvoyListener">EnvoyListener
@@ -7481,6 +7500,23 @@ When it reaches 98% of the maximum heap size, Envoy Will stop accepting requests
 More info: <a href="https://projectcontour.io/docs/main/config/overload-manager/">https://projectcontour.io/docs/main/config/overload-manager/</a></p>
 </td>
 </tr>
+<tr>
+<td style="white-space:nowrap">
+<code>overloadMaxDownstreamConnections</code>
+<br>
+<em>
+uint64
+</em>
+</td>
+<td>
+<em>(Optional)</em>
+<p>OverloadMaxDownstreamConn defines the envoy global downstream connection limit controlled by the overload manager.
+When the value is greater than 0 the overload manager is enabled and listeners
+will begin rejecting connections when the the connection threshold is hit.
+Metrics and health listeners are not subject to the connection limits, however,
+they still count against the global limit.</p>
+</td>
+</tr>
 </tbody>
 </table>
 <h3 id="projectcontour.io/v1alpha1.EnvoyTLS">EnvoyTLS
diff --git a/site/content/docs/main/configuration.md b/site/content/docs/main/configuration.md
index f5cb125e..7fd5b5c2 100644
--- a/site/content/docs/main/configuration.md
+++ b/site/content/docs/main/configuration.md
@@ -103,6 +103,7 @@ Where Contour settings can also be specified with command-line flags, the comman
 | enableExternalNameService | boolean                | `false`                                                                                              | Enable ExternalName Service processing. Enabling this has security implications. Please see the [advisory](https://github.com/projectcontour/contour/security/advisories/GHSA-5ph6-qq5x-7jwc) for more details.                                                                       |
 | metrics                   | MetricsParameters     |                                                                                                       | The [metrics configuration](#metrics-configuration) |
 | featureFlags              | string array           | `[]`                                                                                                 | Defines the toggle to enable new contour features. Available toggles are:  <br/> 1. `useEndpointSlices` - configures contour to fetch endpoint data from k8s endpoint slices.                                                                                                         |
+| omEnforcedHealthListener | OMEnforcedHealthListenerConfig | | The [overload manager enforced health listener config](#overload-manager-enforced-health-listener-config) |
 
 ### TLS Configuration
 
@@ -302,6 +303,18 @@ Sets the compression configuration applied in the compression HTTP filter of the
 |------------|--------|--------|-------------------------|
 | algorithm  | string | "gzip" | Compression algorithm. Setting this to `disabled` will make Envoy skip "Accept-Encoding: gzip,deflate" request header and always return uncompressed response. Values:`gzip` (default), `brotli`, `zstd`, `disabled`. |
 
+### Overload Manager Enforced Health Listener Config
+
+OMEnforcedHealthListenerConfig holds the configuration for a health stats listener that enforces limits imposed by the overload manager,
+notably max global downstream connections. This listener can be used to fail readiness checks without failing liveness to
+load shed connections under heavy load.
+
+By default, this configuration is not enabled.
+
+| Field Name              | Type   | Default | Description                                |
+| ----------------------- | ------ | ------- | ------------------------------------------ |
+| address                 | string | none    | Address that health listener will bind to. |
+| port                    | int    | 0       | Port that health listener will bind to.    |
 
 ### Configuration Example
 
@@ -475,6 +488,10 @@ data:
     #  socket-options:
     #    tos: 64
     #    traffic-class: 64
+    #
+    # omEnforcedHealthListener:
+    #   address: 0.0.0.0
+    #   port: 8003
 ```
 
 _Note:_ The default example `contour` includes this [file][1] for easy deployment of Contour.
@@ -520,6 +537,7 @@ connects to Contour:
 | <nobr>--dns-lookup-family</nobr>       | auto              | Defines what DNS Resolution Policy to use for Envoy -> Contour cluster name lookup. Either v4, v6, auto or all.                                                                                                   |
 | <nobr>--log-format                     | text              | Log output format for Contour. Either text or json. |
 | <nobr>--overload-max-heap              | 0                 | Defines the maximum heap memory of the envoy controlled by the overload manager. When the value is greater than 0, the overload manager is enabled, and when envoy reaches 95% of the maximum heap size, it performs a shrink heap operation. When it reaches 98% of the maximum heap size, Envoy Will stop accepting requests. |
+| <nobr>--overload-downstream-max-conn              | 0                 | 	OverloadMaxDownstreamConn defines the envoy global downstream connection limit controlled by the overload manager. When the value is greater than 0 the overload manager is enabled and listeners will begin rejecting connections when the the connection threshold is hit. Metrics and health listeners are not subject to the connection limits, however, they still count against the global limit. |
 
 
 [1]: {{< param github_url>}}/tree/{{< param branch >}}/examples/contour/01-contour-config.yaml



Test patch:
diff --git a/cmd/contour/servecontext_test.go b/cmd/contour/servecontext_test.go
index 944653ad..b3dfee1f 100644
--- a/cmd/contour/servecontext_test.go
+++ b/cmd/contour/servecontext_test.go
@@ -486,6 +486,7 @@ func defaultContourConfiguration() contour_v1alpha1.ContourConfigurationSpec {
 				XffNumTrustedHops:         ptr.To(uint32(0)),
 				EnvoyStripTrailingHostDot: ptr.To(false),
 			},
+			OMEnforcedHealth: nil,
 		},
 		Gateway: nil,
 		HTTPProxy: &contour_v1alpha1.HTTPProxyConfig{
@@ -902,6 +903,22 @@ func TestConvertServeContext(t *testing.T) {
 				return cfg
 			},
 		},
+		"envoy overload manager health checks": {
+			getServeContext: func(ctx *serveContext) *serveContext {
+				ctx.Config.OMEnforcedHealthListener = &config.OMEnforcedHealthListenerConfig{
+					Address: "0.0.0.0",
+					Port:    8005,
+				}
+				return ctx
+			},
+			getContourConfiguration: func(cfg contour_v1alpha1.ContourConfigurationSpec) contour_v1alpha1.ContourConfigurationSpec {
+				cfg.Envoy.OMEnforcedHealth = &contour_v1alpha1.HealthConfig{
+					Address: "0.0.0.0",
+					Port:    8005,
+				}
+				return cfg
+			},
+		},
 	}
 
 	for name, tc := range cases {
diff --git a/internal/envoy/bootstrap_test.go b/internal/envoy/bootstrap_test.go
index 987058da..688f9441 100644
--- a/internal/envoy/bootstrap_test.go
+++ b/internal/envoy/bootstrap_test.go
@@ -14,6 +14,7 @@
 package envoy
 
 import (
+	"errors"
 	"fmt"
 	"testing"
 
@@ -39,3 +40,22 @@ func TestValidAdminAddress(t *testing.T) {
 		})
 	}
 }
+
+func TestValidConnectionLimit(t *testing.T) {
+	tests := []struct {
+		name      string
+		connLimit int64
+		want      error
+	}{
+		{name: "valid connection limit", connLimit: 10, want: nil},
+		{name: "valid connection limit", connLimit: 0, want: nil},
+		{name: "invalid connection limit", connLimit: -10, want: errors.New("invalid value -10, cannot be < 0")},
+	}
+
+	for _, tc := range tests {
+		t.Run(tc.name, func(t *testing.T) {
+			got := ValidConnectionLimit(tc.connLimit)
+			assert.Equal(t, tc.want, got)
+		})
+	}
+}
diff --git a/internal/envoy/v3/bootstrap_test.go b/internal/envoy/v3/bootstrap_test.go
index 03bbe485..c5470482 100644
--- a/internal/envoy/v3/bootstrap_test.go
+++ b/internal/envoy/v3/bootstrap_test.go
@@ -1800,7 +1800,7 @@ func TestBootstrap(t *testing.T) {
 			},
 			wantedError: true,
 		},
-		"Enable overload manager by specifying --overload-max-heap=2147483648": {
+		"enable fixed heap overload manager by specifying --overload-max-heap=2147483648": {
 			config: envoy.BootstrapConfig{
 				Path:                 "envoy.json",
 				Namespace:            "projectcontour",
@@ -2017,6 +2017,424 @@ func TestBootstrap(t *testing.T) {
         }
       }`,
 		},
+		"enable max downstream connections overload manager by specifying --overload-downstream-max-conn=54321": {
+			config: envoy.BootstrapConfig{
+				Path:                            "envoy.json",
+				Namespace:                       "projectcontour",
+				GlobalDownstreamConnectionLimit: 54321,
+			},
+			wantedBootstrapConfig: `{
+          "static_resources": {
+            "clusters": [
+              {
+                "name": "contour",
+                "alt_stat_name": "projectcontour_contour_8001",
+                "type": "STATIC",
+                "connect_timeout": "5s",
+                "load_assignment": {
+                  "cluster_name": "contour",
+                  "endpoints": [
+                    {
+                      "lb_endpoints": [
+                        {
+                          "endpoint": {
+                            "address": {
+                              "socket_address": {
+                                "address": "127.0.0.1",
+                                "port_value": 8001
+                              }
+                            }
+                          }
+                        }
+                      ]
+                    }
+                  ]
+                },
+                "circuit_breakers": {
+                  "thresholds": [
+                    {
+                      "priority": "HIGH",
+                      "max_connections": 100000,
+                      "max_pending_requests": 100000,
+                      "max_requests": 60000000,
+                      "max_retries": 50,
+                      "track_remaining": true
+                    },
+                    {
+                      "max_connections": 100000,
+                      "max_pending_requests": 100000,
+                      "max_requests": 60000000,
+                      "max_retries": 50,
+                      "track_remaining": true
+                    }
+                  ]
+                },
+                "typed_extension_protocol_options": {
+                  "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": {
+                    "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions",
+                    "explicit_http_config": {
+                      "http2_protocol_options": {}
+                    }
+                  }
+                },
+                "upstream_connection_options": {
+                  "tcp_keepalive": {
+                    "keepalive_probes": 3,
+                    "keepalive_time": 30,
+                    "keepalive_interval": 5
+                  }
+                }
+              },
+              {
+                "name": "envoy-admin",
+                "alt_stat_name": "projectcontour_envoy-admin_9001",
+                "type": "STATIC",
+                "connect_timeout": "0.250s",
+                "load_assignment": {
+                  "cluster_name": "envoy-admin",
+                  "endpoints": [
+                    {
+                      "lb_endpoints": [
+                        {
+                          "endpoint": {
+                            "address": {
+                              "pipe": {
+                                "path": "/admin/admin.sock",
+                                "mode": 420
+                              }
+                            }
+                          }
+                        }
+                      ]
+                    }
+                  ]
+                }
+              }
+            ]
+          },
+          "default_regex_engine": {
+            "name": "envoy.regex_engines.google_re2",
+            "typed_config": {
+              "@type": "type.googleapis.com/envoy.extensions.regex_engines.v3.GoogleRE2"
+            }
+          },
+          "dynamic_resources": {
+            "lds_config": {
+              "api_config_source": {
+                "api_type": "GRPC",
+                "transport_api_version": "V3",
+                "grpc_services": [
+                  {
+                    "envoy_grpc": {
+                      "cluster_name": "contour",
+                      "authority": "contour"
+                    }
+                  }
+                ]
+              },
+              "resource_api_version": "V3"
+            },
+            "cds_config": {
+              "api_config_source": {
+                "api_type": "GRPC",
+                "transport_api_version": "V3",
+                "grpc_services": [
+                  {
+                    "envoy_grpc": {
+                      "cluster_name": "contour",
+                      "authority": "contour"
+                    }
+                  }
+                ]
+              },
+              "resource_api_version": "V3"
+            }
+          },
+          "layered_runtime": {
+            "layers": [
+              {
+                "name": "dynamic",
+                "rtds_layer": {
+                  "name": "dynamic",
+                  "rtds_config": {
+                    "api_config_source": {
+                      "api_type": "GRPC",
+                      "transport_api_version": "V3",
+                      "grpc_services": [
+                        {
+                          "envoy_grpc": {
+                            "cluster_name": "contour",
+                            "authority": "contour"
+                          }
+                        }
+                      ]
+                    },
+                    "resource_api_version": "V3"
+                  }
+                }
+              },
+              {
+                "name": "admin",
+                "admin_layer": {}
+              }
+            ]
+          },
+          "admin": {
+            "access_log": [
+              {
+                "name": "envoy.access_loggers.file",
+                "typed_config": {
+                  "@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog",
+                  "path": "/dev/null"
+                }
+              }
+            ],
+            "address": {
+              "pipe": {
+                "path": "/admin/admin.sock",
+                "mode": 420
+              }
+            }
+          },
+          "overload_manager": {
+            "refresh_interval": "0.250s",
+            "resource_monitors": [
+              {
+                "name": "envoy.resource_monitors.global_downstream_max_connections",
+                "typed_config": {
+                  "@type": "type.googleapis.com/envoy.extensions.resource_monitors.downstream_connections.v3.DownstreamConnectionsConfig",
+                  "max_active_downstream_connections": "54321"
+                }
+              }
+            ]
+          }
+        }`,
+		},
+		"enable max downstream connections and fixed heap overload manager": {
+			config: envoy.BootstrapConfig{
+				Path:                            "envoy.json",
+				Namespace:                       "projectcontour",
+				MaximumHeapSizeBytes:            2147483648, // 2 GiB
+				GlobalDownstreamConnectionLimit: 54321,
+			},
+			wantedBootstrapConfig: `{
+            "static_resources": {
+              "clusters": [
+                {
+                  "name": "contour",
+                  "alt_stat_name": "projectcontour_contour_8001",
+                  "type": "STATIC",
+                  "connect_timeout": "5s",
+                  "load_assignment": {
+                    "cluster_name": "contour",
+                    "endpoints": [
+                      {
+                        "lb_endpoints": [
+                          {
+                            "endpoint": {
+                              "address": {
+                                "socket_address": {
+                                  "address": "127.0.0.1",
+                                  "port_value": 8001
+                                }
+                              }
+                            }
+                          }
+                        ]
+                      }
+                    ]
+                  },
+                  "circuit_breakers": {
+                    "thresholds": [
+                      {
+                        "priority": "HIGH",
+                        "max_connections": 100000,
+                        "max_pending_requests": 100000,
+                        "max_requests": 60000000,
+                        "max_retries": 50,
+                        "track_remaining": true
+                      },
+                      {
+                        "max_connections": 100000,
+                        "max_pending_requests": 100000,
+                        "max_requests": 60000000,
+                        "max_retries": 50,
+                        "track_remaining": true
+                      }
+                    ]
+                  },
+                  "typed_extension_protocol_options": {
+                    "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": {
+                      "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions",
+                      "explicit_http_config": {
+                        "http2_protocol_options": {}
+                      }
+                    }
+                  },
+                  "upstream_connection_options": {
+                    "tcp_keepalive": {
+                      "keepalive_probes": 3,
+                      "keepalive_time": 30,
+                      "keepalive_interval": 5
+                    }
+                  }
+                },
+                {
+                  "name": "envoy-admin",
+                  "alt_stat_name": "projectcontour_envoy-admin_9001",
+                  "type": "STATIC",
+                  "connect_timeout": "0.250s",
+                  "load_assignment": {
+                    "cluster_name": "envoy-admin",
+                    "endpoints": [
+                      {
+                        "lb_endpoints": [
+                          {
+                            "endpoint": {
+                              "address": {
+                                "pipe": {
+                                  "path": "/admin/admin.sock",
+                                  "mode": 420
+                                }
+                              }
+                            }
+                          }
+                        ]
+                      }
+                    ]
+                  }
+                }
+              ]
+            },
+            "default_regex_engine": {
+              "name": "envoy.regex_engines.google_re2",
+              "typed_config": {
+                "@type": "type.googleapis.com/envoy.extensions.regex_engines.v3.GoogleRE2"
+              }
+            },
+            "dynamic_resources": {
+              "lds_config": {
+                "api_config_source": {
+                  "api_type": "GRPC",
+                  "transport_api_version": "V3",
+                  "grpc_services": [
+                    {
+                      "envoy_grpc": {
+                        "cluster_name": "contour",
+                        "authority": "contour"
+                      }
+                    }
+                  ]
+                },
+                "resource_api_version": "V3"
+              },
+              "cds_config": {
+                "api_config_source": {
+                  "api_type": "GRPC",
+                  "transport_api_version": "V3",
+                  "grpc_services": [
+                    {
+                      "envoy_grpc": {
+                        "cluster_name": "contour",
+                        "authority": "contour"
+                      }
+                    }
+                  ]
+                },
+                "resource_api_version": "V3"
+              }
+            },
+            "layered_runtime": {
+              "layers": [
+                {
+                  "name": "dynamic",
+                  "rtds_layer": {
+                    "name": "dynamic",
+                    "rtds_config": {
+                      "api_config_source": {
+                        "api_type": "GRPC",
+                        "transport_api_version": "V3",
+                        "grpc_services": [
+                          {
+                            "envoy_grpc": {
+                              "cluster_name": "contour",
+                              "authority": "contour"
+                            }
+                          }
+                        ]
+                      },
+                      "resource_api_version": "V3"
+                    }
+                  }
+                },
+                {
+                  "name": "admin",
+                  "admin_layer": {}
+                }
+              ]
+            },
+            "admin": {
+              "access_log": [
+                {
+                  "name": "envoy.access_loggers.file",
+                  "typed_config": {
+                    "@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog",
+                    "path": "/dev/null"
+                  }
+                }
+              ],
+              "address": {
+                "pipe": {
+                  "path": "/admin/admin.sock",
+                  "mode": 420
+                }
+              }
+            },
+            "overload_manager": {
+              "refresh_interval": "0.250s",
+              "resource_monitors": [
+                {
+                  "name": "envoy.resource_monitors.fixed_heap",
+                  "typed_config": {
+                    "@type": "type.googleapis.com/envoy.extensions.resource_monitors.fixed_heap.v3.FixedHeapConfig",
+                    "max_heap_size_bytes": "2147483648"
+                  }
+                },
+                {
+                  "name": "envoy.resource_monitors.global_downstream_max_connections",
+                  "typed_config": {
+                    "@type": "type.googleapis.com/envoy.extensions.resource_monitors.downstream_connections.v3.DownstreamConnectionsConfig",
+                    "max_active_downstream_connections": "54321"
+                  }
+                }
+              ],
+              "actions": [
+                {
+                  "name": "envoy.overload_actions.shrink_heap",
+                  "triggers": [
+                    {
+                      "name": "envoy.resource_monitors.fixed_heap",
+                      "threshold": {
+                        "value": 0.95
+                      }
+                    }
+                  ]
+                },
+                {
+                  "name": "envoy.overload_actions.stop_accepting_requests",
+                  "triggers": [
+                    {
+                      "name": "envoy.resource_monitors.fixed_heap",
+                      "threshold": {
+                        "value": 0.98
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }`,
+		},
 	}
 
 	for name, tc := range tests {
diff --git a/internal/envoy/v3/stats_test.go b/internal/envoy/v3/stats_test.go
index b86b37da..b312041d 100644
--- a/internal/envoy/v3/stats_test.go
+++ b/internal/envoy/v3/stats_test.go
@@ -120,23 +120,25 @@ func TestStatsListeners(t *testing.T) {
 	})
 
 	type testcase struct {
-		metrics contour_v1alpha1.MetricsConfig
-		health  contour_v1alpha1.HealthConfig
-		want    []*envoy_config_listener_v3.Listener
+		metrics        contour_v1alpha1.MetricsConfig
+		health         contour_v1alpha1.HealthConfig
+		omHealthConfig *contour_v1alpha1.HealthConfig
+		want           []*envoy_config_listener_v3.Listener
 	}
 
 	run := func(t *testing.T, name string, tc testcase) {
 		t.Helper()
 		t.Run(name, func(t *testing.T) {
 			t.Helper()
-			got := envoyGen.StatsListeners(tc.metrics, tc.health)
+			got := envoyGen.StatsListeners(tc.metrics, tc.health, tc.omHealthConfig)
 			protobuf.ExpectEqual(t, tc.want, got)
 		})
 	}
 
 	run(t, "stats-and-health-over-http-single-listener", testcase{
-		metrics: contour_v1alpha1.MetricsConfig{Address: "127.0.0.127", Port: 8123},
-		health:  contour_v1alpha1.HealthConfig{Address: "127.0.0.127", Port: 8123},
+		metrics:        contour_v1alpha1.MetricsConfig{Address: "127.0.0.127", Port: 8123},
+		health:         contour_v1alpha1.HealthConfig{Address: "127.0.0.127", Port: 8123},
+		omHealthConfig: nil,
 		want: []*envoy_config_listener_v3.Listener{{
 			Name:    "stats-health",
 			Address: SocketAddress("127.0.0.127", 8123),
@@ -166,7 +168,8 @@ func TestStatsListeners(t *testing.T) {
 					},
 				},
 			),
-			SocketOptions: NewSocketOptions().TCPKeepalive().Build(),
+			SocketOptions:         NewSocketOptions().TCPKeepalive().Build(),
+			IgnoreGlobalConnLimit: true,
 		}},
 	})
 
@@ -183,6 +186,7 @@ func TestStatsListeners(t *testing.T) {
 			Address: "127.0.0.127",
 			Port:    8124,
 		},
+		omHealthConfig: nil,
 		want: []*envoy_config_listener_v3.Listener{{
 			Name:    "stats",
 			Address: SocketAddress("127.0.0.127", 8123),
@@ -226,7 +230,8 @@ func TestStatsListeners(t *testing.T) {
 					},
 				),
 			}},
-			SocketOptions: NewSocketOptions().TCPKeepalive().Build(),
+			SocketOptions:         NewSocketOptions().TCPKeepalive().Build(),
+			IgnoreGlobalConnLimit: true,
 		}, {
 			Name:    "health",
 			Address: SocketAddress("127.0.0.127", 8124),
@@ -256,7 +261,8 @@ func TestStatsListeners(t *testing.T) {
 					},
 				},
 			),
-			SocketOptions: NewSocketOptions().TCPKeepalive().Build(),
+			SocketOptions:         NewSocketOptions().TCPKeepalive().Build(),
+			IgnoreGlobalConnLimit: true,
 		}},
 	})
 
@@ -274,6 +280,7 @@ func TestStatsListeners(t *testing.T) {
 			Address: "127.0.0.127",
 			Port:    8124,
 		},
+		omHealthConfig: nil,
 		want: []*envoy_config_listener_v3.Listener{{
 			Name:    "stats",
 			Address: SocketAddress("127.0.0.127", 8123),
@@ -324,7 +331,8 @@ func TestStatsListeners(t *testing.T) {
 					},
 				),
 			}},
-			SocketOptions: NewSocketOptions().TCPKeepalive().Build(),
+			SocketOptions:         NewSocketOptions().TCPKeepalive().Build(),
+			IgnoreGlobalConnLimit: true,
 		}, {
 			Name:    "health",
 			Address: SocketAddress("127.0.0.127", 8124),
@@ -354,7 +362,8 @@ func TestStatsListeners(t *testing.T) {
 					},
 				},
 			),
-			SocketOptions: NewSocketOptions().TCPKeepalive().Build(),
+			SocketOptions:         NewSocketOptions().TCPKeepalive().Build(),
+			IgnoreGlobalConnLimit: true,
 		}},
 	})
 
@@ -367,6 +376,7 @@ func TestStatsListeners(t *testing.T) {
 			Address: "127.0.0.128",
 			Port:    8124,
 		},
+		omHealthConfig: nil,
 		want: []*envoy_config_listener_v3.Listener{{
 			Name:    "stats",
 			Address: SocketAddress("127.0.0.127", 8123),
@@ -396,7 +406,8 @@ func TestStatsListeners(t *testing.T) {
 					},
 				},
 			),
-			SocketOptions: NewSocketOptions().TCPKeepalive().Build(),
+			SocketOptions:         NewSocketOptions().TCPKeepalive().Build(),
+			IgnoreGlobalConnLimit: true,
 		}, {
 			Name:    "health",
 			Address: SocketAddress("127.0.0.128", 8124),
@@ -426,7 +437,77 @@ func TestStatsListeners(t *testing.T) {
 					},
 				},
 			),
-			SocketOptions: NewSocketOptions().TCPKeepalive().Build(),
+			SocketOptions:         NewSocketOptions().TCPKeepalive().Build(),
+			IgnoreGlobalConnLimit: true,
+		}},
+	})
+
+	run(t, "stats-and-health-over-http-single-listener-with-om-enforced-health-listener", testcase{
+		metrics:        contour_v1alpha1.MetricsConfig{Address: "127.0.0.127", Port: 8123},
+		health:         contour_v1alpha1.HealthConfig{Address: "127.0.0.127", Port: 8123},
+		omHealthConfig: &contour_v1alpha1.HealthConfig{Address: "127.0.0.127", Port: 8124},
+		want: []*envoy_config_listener_v3.Listener{{
+			Name:    "stats-health",
+			Address: SocketAddress("127.0.0.127", 8123),
+			FilterChains: FilterChains(
+				&envoy_config_listener_v3.Filter{
+					Name: wellknown.HTTPConnectionManager,
+					ConfigType: &envoy_config_listener_v3.Filter_TypedConfig{
+						TypedConfig: protobuf.MustMarshalAny(&envoy_filter_network_http_connection_manager_v3.HttpConnectionManager{
+							StatPrefix: "stats",
+							RouteSpecifier: &envoy_filter_network_http_connection_manager_v3.HttpConnectionManager_RouteConfig{
+								RouteConfig: &envoy_config_route_v3.RouteConfiguration{
+									VirtualHosts: []*envoy_config_route_v3.VirtualHost{{
+										Name:    "backend",
+										Domains: []string{"*"},
+										Routes:  []*envoy_config_route_v3.Route{readyRoute, statsRoute, prometheusStatsRoute},
+									}},
+								},
+							},
+							HttpFilters: []*envoy_filter_network_http_connection_manager_v3.HttpFilter{{
+								Name: wellknown.Router,
+								ConfigType: &envoy_filter_network_http_connection_manager_v3.HttpFilter_TypedConfig{
+									TypedConfig: protobuf.MustMarshalAny(&envoy_filter_http_router_v3.Router{}),
+								},
+							}},
+							NormalizePath: wrapperspb.Bool(true),
+						}),
+					},
+				},
+			),
+			SocketOptions:         NewSocketOptions().TCPKeepalive().Build(),
+			IgnoreGlobalConnLimit: true,
+		}, {
+			Name:    "health-om-enforced",
+			Address: SocketAddress("127.0.0.127", 8124),
+			FilterChains: FilterChains(
+				&envoy_config_listener_v3.Filter{
+					Name: wellknown.HTTPConnectionManager,
+					ConfigType: &envoy_config_listener_v3.Filter_TypedConfig{
+						TypedConfig: protobuf.MustMarshalAny(&envoy_filter_network_http_connection_manager_v3.HttpConnectionManager{
+							StatPrefix: "stats",
+							RouteSpecifier: &envoy_filter_network_http_connection_manager_v3.HttpConnectionManager_RouteConfig{
+								RouteConfig: &envoy_config_route_v3.RouteConfiguration{
+									VirtualHosts: []*envoy_config_route_v3.VirtualHost{{
+										Name:    "backend",
+										Domains: []string{"*"},
+										Routes:  []*envoy_config_route_v3.Route{readyRoute},
+									}},
+								},
+							},
+							HttpFilters: []*envoy_filter_network_http_connection_manager_v3.HttpFilter{{
+								Name: wellknown.Router,
+								ConfigType: &envoy_filter_network_http_connection_manager_v3.HttpFilter_TypedConfig{
+									TypedConfig: protobuf.MustMarshalAny(&envoy_filter_http_router_v3.Router{}),
+								},
+							}},
+							NormalizePath: wrapperspb.Bool(true),
+						}),
+					},
+				},
+			),
+			SocketOptions:         NewSocketOptions().TCPKeepalive().Build(),
+			IgnoreGlobalConnLimit: false,
 		}},
 	})
 }
diff --git a/internal/featuretests/v3/envoy.go b/internal/featuretests/v3/envoy.go
index c50e5e25..e9b8a599 100644
--- a/internal/featuretests/v3/envoy.go
+++ b/internal/featuretests/v3/envoy.go
@@ -656,7 +656,8 @@ func statsListener() *envoy_config_listener_v3.Listener {
 		XDSClusterName: envoy_v3.DefaultXDSClusterName,
 	}).StatsListeners(
 		contour_v1alpha1.MetricsConfig{Address: "0.0.0.0", Port: 8002},
-		contour_v1alpha1.HealthConfig{Address: "0.0.0.0", Port: 8002})
+		contour_v1alpha1.HealthConfig{Address: "0.0.0.0", Port: 8002},
+		nil)
 	return listeners[0]
 }
 
diff --git a/internal/featuretests/v3/featuretests.go b/internal/featuretests/v3/featuretests.go
index 559f6bb9..3b82e7fb 100644
--- a/internal/featuretests/v3/featuretests.go
+++ b/internal/featuretests/v3/featuretests.go
@@ -102,6 +102,7 @@ func setup(t *testing.T, opts ...any) (ResourceEventHandlerWrapper, *Contour, fu
 			conf,
 			contour_v1alpha1.MetricsConfig{Address: "0.0.0.0", Port: 8002},
 			contour_v1alpha1.HealthConfig{Address: "0.0.0.0", Port: 8002},
+			nil,
 			0,
 			envoyGen,
 		),
diff --git a/internal/featuretests/v3/listeners_test.go b/internal/featuretests/v3/listeners_test.go
index 525c7601..69aec702 100644
--- a/internal/featuretests/v3/listeners_test.go
+++ b/internal/featuretests/v3/listeners_test.go
@@ -50,6 +50,7 @@ func customAdminPort(t *testing.T, port int) []xdscache.ResourceCache {
 			conf,
 			contour_v1alpha1.MetricsConfig{Address: "0.0.0.0", Port: 8002},
 			contour_v1alpha1.HealthConfig{Address: "0.0.0.0", Port: 8002},
+			nil,
 			port,
 			envoy_v3.NewEnvoyGen(envoy_v3.EnvoyGenOpt{
 				XDSClusterName: envoy_v3.DefaultXDSClusterName,
diff --git a/internal/provisioner/controller/gateway_test.go b/internal/provisioner/controller/gateway_test.go
index 0cf9721d..fc5383f8 100644
--- a/internal/provisioner/controller/gateway_test.go
+++ b/internal/provisioner/controller/gateway_test.go
@@ -1178,6 +1178,56 @@ func TestGatewayReconcile(t *testing.T) {
 			},
 		},
 
+		"If ContourDeployment.Spec.Envoy.OverloadMaxDownstreamConnections is specified, the envoy-initconfig container's arguments contain --overload-downstream-max-conn": {
+			gatewayClass: reconcilableGatewayClassWithParams("gatewayclass-1", controller),
+			gatewayClassParams: &contour_v1alpha1.ContourDeployment{
+				ObjectMeta: meta_v1.ObjectMeta{
+					Namespace: "projectcontour",
+					Name:      "gatewayclass-1-params",
+				},
+				Spec: contour_v1alpha1.ContourDeploymentSpec{
+					Envoy: &contour_v1alpha1.EnvoySettings{
+						OverloadMaxDownstreamConnections: 20000000,
+					},
+				},
+			},
+			gateway: makeGateway(),
+			assertions: func(t *testing.T, r *gatewayReconciler, _ *gatewayapi_v1.Gateway, _ error) {
+				ds := &apps_v1.DaemonSet{
+					ObjectMeta: meta_v1.ObjectMeta{
+						Namespace: "gateway-1",
+						Name:      "envoy-gateway-1",
+					},
+				}
+				require.NoError(t, r.client.Get(context.Background(), keyFor(ds), ds))
+				assert.Contains(t, ds.Spec.Template.Spec.InitContainers[0].Args, "--overload-downstream-max-conn=20000000")
+			},
+		},
+
+		"If ContourDeployment.Spec.Envoy.OverloadMaxDownstreamConnections is not specified, the envoy-initconfig container's arguments contain --overload-downstream-max-conn=0": {
+			gatewayClass: reconcilableGatewayClassWithParams("gatewayclass-1", controller),
+			gatewayClassParams: &contour_v1alpha1.ContourDeployment{
+				ObjectMeta: meta_v1.ObjectMeta{
+					Namespace: "projectcontour",
+					Name:      "gatewayclass-1-params",
+				},
+				Spec: contour_v1alpha1.ContourDeploymentSpec{
+					Envoy: &contour_v1alpha1.EnvoySettings{},
+				},
+			},
+			gateway: makeGateway(),
+			assertions: func(t *testing.T, r *gatewayReconciler, _ *gatewayapi_v1.Gateway, _ error) {
+				ds := &apps_v1.DaemonSet{
+					ObjectMeta: meta_v1.ObjectMeta{
+						Namespace: "gateway-1",
+						Name:      "envoy-gateway-1",
+					},
+				}
+				require.NoError(t, r.client.Get(context.Background(), keyFor(ds), ds))
+				assert.Contains(t, ds.Spec.Template.Spec.InitContainers[0].Args, "--overload-downstream-max-conn=0")
+			},
+		},
+
 		"If ContourDeployment.Spec.Contour.PodAnnotations is specified, the Contour pods' have annotations for prometheus & user-defined": {
 			gatewayClass: reconcilableGatewayClassWithParams("gatewayclass-1", controller),
 			gatewayClassParams: &contour_v1alpha1.ContourDeployment{
diff --git a/internal/provisioner/objects/dataplane/dataplane_test.go b/internal/provisioner/objects/dataplane/dataplane_test.go
index 55d6cd51..f15e0e43 100644
--- a/internal/provisioner/objects/dataplane/dataplane_test.go
+++ b/internal/provisioner/objects/dataplane/dataplane_test.go
@@ -314,6 +314,7 @@ func TestDesiredDaemonSet(t *testing.T) {
 	testLogLevelArg := "--log-level debug"
 	testBaseIDArg := "--base-id 1"
 	testEnvoyMaxHeapSize := "--overload-max-heap=8000000000"
+	testEnvoyMaxDownstreamConn := "--overload-downstream-max-conn=42"
 
 	resQutoa := core_v1.ResourceRequirements{
 		Limits: core_v1.ResourceList{
@@ -340,6 +341,7 @@ func TestDesiredDaemonSet(t *testing.T) {
 	cntr.Spec.EnvoyBaseID = 1
 
 	cntr.Spec.EnvoyMaxHeapSizeBytes = 8000000000
+	cntr.Spec.EnvoyMaxDownstreamConnections = 42
 
 	ds := DesiredDaemonSet(cntr, testContourImage, testEnvoyImage)
 	container := checkDaemonSetHasContainer(t, ds, EnvoyContainerName, true)
@@ -357,6 +359,7 @@ func TestDesiredDaemonSet(t *testing.T) {
 
 	checkContainerHasImage(t, container, testContourImage)
 	checkContainerHasArg(t, container, testEnvoyMaxHeapSize)
+	checkContainerHasArg(t, container, testEnvoyMaxDownstreamConn)
 
 	checkDaemonSetHasEnvVar(t, ds, EnvoyContainerName, envoyNsEnvVar)
 	checkDaemonSetHasEnvVar(t, ds, EnvoyContainerName, envoyPodEnvVar)
diff --git a/test/e2e/bootstrap/bootstrap_test.go b/test/e2e/bootstrap/bootstrap_test.go
new file mode 100644
index 00000000..7dc61afa
--- /dev/null
+++ b/test/e2e/bootstrap/bootstrap_test.go
@@ -0,0 +1,104 @@
+// Copyright Project Contour Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//go:build e2e
+
+package bootstrap
+
+import (
+	"testing"
+
+	. "github.com/onsi/ginkgo/v2"
+	. "github.com/onsi/gomega"
+	"github.com/onsi/gomega/gexec"
+	"github.com/stretchr/testify/require"
+
+	contour_v1alpha1 "github.com/projectcontour/contour/apis/projectcontour/v1alpha1"
+	"github.com/projectcontour/contour/pkg/config"
+	"github.com/projectcontour/contour/test/e2e"
+)
+
+var (
+	f = e2e.NewFramework(false)
+
+	// Functions called after suite to clean up resources.
+	cleanup []func()
+)
+
+func TestBootstrap(t *testing.T) {
+	RegisterFailHandler(Fail)
+	RunSpecs(t, "Bootstrap tests")
+}
+
+var _ = BeforeSuite(func() {
+	// add overload manager arguments to envoy bootstrap
+	f.Deployment.ContourBootstrapExtraArgs = []string{
+		"--overload-max-heap=987654321",
+		"--overload-downstream-max-conn=1",
+	}
+
+	require.NoError(f.T(), f.Deployment.EnsureResourcesForLocalContour())
+})
+
+var _ = AfterSuite(func() {
+	for _, c := range cleanup {
+		c()
+	}
+	require.NoError(f.T(), f.Deployment.DeleteResourcesForLocalContour())
+	gexec.CleanupBuildArtifacts()
+})
+
+var _ = Describe("Bootstrap", func() {
+	var (
+		contourCmd           *gexec.Session
+		kubectlCmd           *gexec.Session
+		contourConfig        *config.Parameters
+		contourConfiguration *contour_v1alpha1.ContourConfiguration
+		contourConfigFile    string
+	)
+
+	BeforeEach(func() {
+		contourConfig = e2e.DefaultContourConfigFileParams()
+		contourConfiguration = e2e.DefaultContourConfiguration()
+	})
+
+	JustBeforeEach(func() {
+		var err error
+		contourCmd, contourConfigFile, err = f.Deployment.StartLocalContour(contourConfig, contourConfiguration)
+		require.NoError(f.T(), err)
+
+		// Wait for Envoy to be healthy.
+		require.NoError(f.T(), f.Deployment.WaitForEnvoyUpdated())
+
+		kubectlCmd, err = f.Kubectl.StartKubectlPortForward(19001, 9001, "projectcontour", f.Deployment.EnvoyResourceAndName())
+		require.NoError(f.T(), err)
+	})
+
+	AfterEach(func() {
+		f.Kubectl.StopKubectlPortForward(kubectlCmd)
+		require.NoError(f.T(), f.Deployment.StopLocalContour(contourCmd, contourConfigFile))
+	})
+
+	f.Test(func() {
+		Specify("requests to default ready listener are served", func() {
+			t := f.T()
+
+			res, ok := f.HTTP.MetricsRequestUntil(&e2e.HTTPRequestOpts{
+				Path:      "/ready",
+				Condition: e2e.HasStatusCode(200),
+			})
+			require.NotNil(t, res, "request never succeeded")
+			require.Truef(t, ok, "expected 200 response code, got %d", res.StatusCode)
+		})
+	})
+})
diff --git a/test/e2e/deployment.go b/test/e2e/deployment.go
index f98437ec..65611fab 100644
--- a/test/e2e/deployment.go
+++ b/test/e2e/deployment.go
@@ -104,6 +104,9 @@ type Deployment struct {
 	EnvoyExtraVolumes      []core_v1.Volume
 	EnvoyExtraVolumeMounts []core_v1.VolumeMount
 
+	// Optional additional args to pass to the bootstrap subcommand
+	ContourBootstrapExtraArgs []string
+
 	// Ratelimit deployment.
 	RateLimitDeployment       *apps_v1.Deployment
 	RateLimitService          *core_v1.Service
@@ -475,14 +478,20 @@ func (d *Deployment) EnsureResourcesForLocalContour() error {
 
 	// Generate bootstrap config with Contour local address and plaintext
 	// client config.
-	bootstrapCmd := exec.Command( // nolint:gosec
-		d.contourBin,
+	bootstrapCmdArgs := []string{
 		"bootstrap",
 		bFile.Name(),
-		"--xds-address="+d.localContourHost,
-		"--xds-port="+d.localContourPort,
+		"--xds-address=" + d.localContourHost,
+		"--xds-port=" + d.localContourPort,
 		"--xds-resource-version=v3",
 		"--admin-address=/admin/admin.sock",
+	}
+
+	bootstrapCmdArgs = append(bootstrapCmdArgs, d.ContourBootstrapExtraArgs...)
+
+	bootstrapCmd := exec.Command( // nolint:gosec
+		d.contourBin,
+		bootstrapCmdArgs...,
 	)
 
 	session, err := gexec.Start(bootstrapCmd, d.cmdOutputWriter, d.cmdOutputWriter)