Load Balancing & Reverse Proxy
Synapse is a reverse proxy before it is anything else. Traffic terminates at it, is inspected, and is forwarded to whichever of your backends is healthy — and the security features are not bolted on beside that path, they are that path.
The practical consequence: you do not run a proxy and a WAF and a fingerprinting layer. You run one hop.
What it gives you
- Balancing across healthy backends, with unhealthy ones taken out of rotation automatically.
- Sticky sessions when a client needs to keep landing on the same backend.
- Client fingerprints forwarded upstream, so your application can see who connected, not just from where.
- Layered headers and timeouts — set a default once, override per host, override again per route.
- HTTP/2 and gRPC, including cleartext, for backends that expect it.
How traffic reaches a backend
- A connection arrives on the HTTP or TLS listener.
- The host decides how it is handled — Synapse either terminates TLS and inspects the request, or passes the connection straight through untouched.
- For terminated traffic, security runs here: threat detection enriches it, the WAF evaluates it, content scanning scans it if configured.
- A healthy upstream is chosen and the request is forwarded.
Terminate or pass through
| Mode | What happens | Use it when |
|---|---|---|
| Terminate | Synapse holds the certificate, decrypts, inspects, then forwards | You want the WAF, content scanning, or HTTP-level rules |
| Passthrough | The connection is forwarded encrypted, by SNI, without decryption | The backend must own TLS, or you cannot hold the key |
Passthrough is chosen per host, and matches wildcards the way DNS does — one label deep, with exact names always winning over a wildcard.
Inspection needs termination. A passthrough host gets connection-level controls only; there is no HTTP request to apply a WAF rule to.
Health checking
Backends are probed on an interval and removed from rotation when they stop answering. The probe method is yours to choose — a HEAD is cheapest, a GET exercises more of the path, and the right answer depends on what your backend does on each.
A backend that fails its probe stops receiving traffic without you intervening, and returns when it recovers.
Sticky sessions
Off by default, because most services do not need it and it costs you even distribution. When enabled, a client is consistently hashed to the same backend across reconnects — useful for a backend holding per-session state that is not shared.
Prefer shared state when you can. Stickiness makes one backend's failure visible to the specific users pinned to it.
Fingerprints forwarded to your application
This is the part that is hard to get elsewhere. The proxy forwards the client's JA4+ fingerprints upstream as request headers, so your own code can act on them:
X-JA4 · X-JA4T · X-JA4H · X-JA4S · X-JA4L · X-JA4X
Your application can then treat a client's TLS or HTTP fingerprint as an input — rate-limit by it, require step-up authentication on an unfamiliar one, or record it alongside a transaction — without implementing any of the capture itself. See JA4+ for what each covers.
Forwarding is on by default and can be turned off if you would rather your backends never see it.
Layered configuration
Headers and timeouts resolve global → host → route, each layer extending the one above rather than replacing it. Set a security header once at the top and it applies everywhere; override a slow endpoint's read timeout at the route without restating the rest.
Limits worth knowing
- Inspection requires termination. A passthrough host cannot be WAF'd, scanned, or matched on HTTP fields.
- Health checks prove reachability, not correctness. A backend answering
200onHEAD /while failing real requests stays in rotation. - Stickiness is by client address. Clients behind a shared egress hash together, and a client whose address changes moves backend.
Use cases
- Put one hop in front of a service and get balancing, TLS, WAF and fingerprinting from it.
- Drain a backend for maintenance by letting it fail its health check, with no config change.
- Give your application client identity it could not otherwise compute, through forwarded fingerprint headers.
- Front a backend that must terminate its own TLS by passing the connection through while keeping connection-level controls.
See also
- Configuration — listeners, upstreams, timeouts and health checks
- Kubernetes Ingress — the same proxy as an Ingress and Gateway API controller
- WAF — what runs on terminated traffic
- JA4+ — the fingerprints forwarded upstream