# Fail Over Between Backends and Regions

> **Scope of this page**
>
> This page documents the Zuplo **gateway** runtime (API, AI, and MCP gateways), not the Developer Portal.
>
> It applies to every Zuplo hosting option: Managed Edge, Managed Dedicated, and Self-Hosted. See [Hosting options](https://zuplo.com/docs/articles/hosting-options).

When your backend runs in more than one region, or you keep a standby copy for
disaster recovery, requests need to reach a healthy copy when another one fails.
Handle failover with a load balancer in front of your backends: it checks the
health of each region and sends traffic only to healthy ones, while Zuplo
forwards every request to one hostname.

:::note

The built-in [URL Forward](../handlers/url-forward.mdx) and
[URL Rewrite](../handlers/url-rewrite.mdx) handlers send each request to the one
URL you configure. They don't run health checks or fail over between backends,
so failover belongs in a load balancer in front of your backends.

:::

## Put a load balancer in front of your backends

Put a service that does health-checked failover in front of your regional
backends and point Zuplo at its hostname. Examples include AWS Global
Accelerator, DNS failover routing, and global load balancers from your cloud or
CDN provider.

<Diagram height="h-64">
  <DiagramNode id="gateway" variant="zuplo">
    Zuplo Gateway
  </DiagramNode>
  <DiagramNode id="lb" variant="orange">
    Global load balancer or DNS
  </DiagramNode>
  <DiagramNode id="primary" variant="green">
    Primary region
  </DiagramNode>
  <DiagramNode id="secondary" variant="blue">
    Secondary region
  </DiagramNode>
  <DiagramEdge from="gateway" to="lb" label="api-origin.example.com" />
  <DiagramEdge from="lb" to="primary" label="healthy" />
  <DiagramEdge from="lb" to="secondary" label="on failover" />
</Diagram>

This keeps failover out of the gateway:

- **Zuplo configuration stays the same.** Your routes, policies, and backend URL
  don't change when a region fails or recovers.
- **Failover doesn't wait for a deployment.** The load balancer or DNS service
  moves traffic based on its own health checks, and you can switch regions by
  hand, for testing or planned maintenance, without redeploying the gateway.
- **Unhealthy regions don't slow requests down.** The service stops sending
  traffic to a failed region, so requests don't wait for a failed attempt first.

### Use a hostname your certificates cover

Zuplo verifies the TLS certificate of every backend it calls, so the backend URL
must use a hostname that the server certificate covers. Create a hostname you
own, such as `api-origin.example.com`, that points at the load balancer or DNS
service. Install a server certificate for that hostname on the endpoint in every
region. Don't use the provider's generated hostname or a static IP address as
the backend URL, because your regional certificates don't cover them.

Store the hostname in an
[environment variable](../articles/environment-variables.mdx) and read it in
your route handlers:

```json title="config/routes.oas.json"
{
  "handler": {
    "export": "urlForwardHandler",
    "module": "$import(@zuplo/runtime)",
    "options": {
      "baseUrl": "${env.BACKEND_URL}"
    }
  }
}
```

### Use the same client certificate in every region

If your backends require mutual TLS, Zuplo presents the same
[client certificate](../articles/securing-backend-mtls.mdx) to whichever region
receives the request. Configure every region to trust the CA that issued that
certificate. For AWS load balancers, see
[Connect to an AWS ALB with mTLS](../articles/connect-to-aws-alb-with-mtls.mdx#use-the-certificate-with-more-than-one-alb).

### Test the secondary region

Before you rely on the secondary region, send test traffic to it through a
[preview environment](../articles/environments.mdx) whose `BACKEND_URL` points
directly at that region. Production traffic is unaffected. See
[Testing Preview Environments](../articles/testing-preview-environments.mdx).

## Monitor backend health

Add a health check route to your gateway that calls each backend, and point your
monitoring service at it. You find out about a failed region even when failover
hides it from your users. See
[Health Check Handler](../articles/health-checks.mdx).

## Next steps

- [Route to Different Backends Based on Geolocation](./geolocation-backend-routing.mdx)
- [Securing your backend](../articles/securing-your-backend.mdx)
