> ## Documentation Index
> Fetch the complete documentation index at: https://firebolt-aggregate-helm-docs-pr-53.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Gateway overview

> Per-instance Envoy gateway for query routing and zero-downtime engine cutovers.

## Overview

The Firebolt Operator Gateway is based on [Envoy Proxy](https://www.envoyproxy.io/) and responsible for query routing.
It uses a Lua filter to pick the target Engine from the `X-Firebolt-Engine` request header or the `engine` query
parameter and a dynamic forward proxy (DFP) to resolve the per-Engine headless Service at request time. The Gateway
removes the routing-only query parameter before forwarding the request to the Engine.

* [Gateway query routing](./gateway-query-routing) describes Envoy routing, retries, graceful shutdown, and why the Firebolt Operator does not gate on EndpointSlice updates.
* [Gateway sizing](./gateway-sizing) describes replica count, memory limits, and the 2 MiB per-connection buffer constraint.

## Connect to engines

### Instance gateway (recommended)

The recommended entry point is the instance gateway. The Envoy proxy routes requests based on the target engine name and handles retries during blue-green transitions. Pass the engine with the `X-Firebolt-Engine` header (raw HTTP clients) or the `engine` query parameter (the bundled `firebolt` CLI).

```text theme={"theme":{"light":"css-variables","dark":"css-variables"}}
POST http://<instance-name>-gateway.<namespace>.svc.cluster.local/
Headers:
  X-Firebolt-Engine: my-engine
  Content-Type: text/plain
Body: <SQL>
```

With the Firebolt CLI from an engine pod:

```bash theme={"theme":{"light":"css-variables","dark":"css-variables"}}
firebolt client \
  --endpoint http://<instance-name>-gateway \
  --insecure \
  --set engine=my-engine \
  -c "SELECT 42" \
  --no-interactive
```

### Per-engine service

Each engine also exposes a headless Service at `<engine>-service.<namespace>.svc.cluster.local:3473`. Use this when your client implements its own connection-level load balancing and DNS re-resolution.

With this entry point the caller is responsible for:

* Periodically re-resolving the Service hostname so that newly ready pods are picked up and draining pods are dropped.
* Treating a request on a single endpoint that fails with a transport error as "pick another endpoint", not "retry this request".

### Configuration

The gateway ConfigMap (`{instance}-gateway-config`) is a pure function of the `FireboltInstance`. The Firebolt Operator does not regenerate it on engine create, delete, scale, or blue-green events, so those events never trigger a gateway rollout.

### Gateway custom service account

By default the Firebolt Operator creates a ServiceAccount named `<instance>-gateway` and a RoleBinding tying it to the chart-managed `<release>-gateway-wake` ClusterRole, which grants `get` / `list` / `watch` on `endpointslices` in the instance's namespace.

That read is the wake-agent sidecar's entire Kubernetes grant: it watches for a stopped engine's endpoints appearing so it can release the query it is holding. Nothing in the gateway pod can write to the API, and the Envoy container holds no token at all — the pod sets `automountServiceAccountToken: false` and projects the token into the agent container alone. See [Auto-stop and wake-up](../../engine/auto-stop-and-wake-up#gateway-wake-up-protocol).

When `spec.gateway.template.spec.serviceAccountName` is set, the Firebolt Operator interprets this as the user taking ownership of the gateway's identity and **skips creating the SA and RoleBinding entirely**. It also **turns off wake-on-zero for that gateway**: the wake-agent sidecar and its hold hook are not rendered, so queries for auto-stopped engines return `503` and do not wake them, exactly as when the [wake agent is disabled in the chart](../../engine/auto-stop-and-wake-up#disabling-wake). Engines still scale up on `spec.autoStop.schedule` windows. The Firebolt Operator records a `WakeOnZeroDisabled` warning event on the `FireboltInstance` when this applies.

You are responsible for creating the ServiceAccount in the instance's namespace under the name you specified. It needs no Kubernetes permissions: with the wake agent gone, nothing in the gateway pod talks to the API.

Taking ownership of the ServiceAccount also means taking ownership of the pod's token: the Firebolt Operator no longer forces `automountServiceAccountToken: false`, and your value on `spec.gateway.template.spec` applies. Set it to `false` unless a sidecar of your own needs API access.

The common reason to override is IRSA / Pod Identity: annotate the SA with the IAM role binding. For IRSA, you can also annotate the Firebolt Operator-managed SA (`spec.gateway.template.metadata.annotations`) and leave `serviceAccountName` unset. That path keeps the Firebolt Operator in charge of the RBAC, and keeps wake-on-zero available.

A missing user ServiceAccount does **not** fail at admission: the gateway pod fails to start with `ServiceAccount … not found` on the kubelet event stream. Create the SA before pointing the Instance at it.

## Rolling update parameters

### Gateway deployment

| Parameter           | Value               | Rationale                                                  |
| ------------------- | ------------------- | ---------------------------------------------------------- |
| `maxSurge`          | `25%`               | Standard Kubernetes default for gradual rollout            |
| `maxUnavailable`    | `0`                 | Maintain full capacity during image switches               |
| PodDisruptionBudget | `maxUnavailable: 1` | Allow voluntary disruptions while maintaining availability |
