Production Deployment Checklist
Use this checklist after you have selected a supported API7 Gateway version and before you send production traffic to the data plane. It focuses on the gateway instances that process API traffic. The control plane and its database must also be deployed for high availability as described in Deploy for High Availability.
Kubernetes with Helm is the recommended option when you need orchestration, automatic rescheduling, rolling updates, and autoscaling. If you run API7 Gateway on Docker hosts, manage each instance with Docker Compose rather than independent docker run commands. Docker Compose does not provide multi-host high availability by itself, so production Docker deployments require multiple hosts and an external load balancer.
Before You Deploy
- Pin supported versions. Pin the Helm chart and container image to versions compatible with your control plane. Do not use
latest. See Supported Versions and Interoperability. - Select a CPU allocation per gateway instance. Start with the production system requirements, then load test representative routes, plugins, payloads, TLS traffic, and logging settings.
- Match workers to CPU cores. Configure one NGINX worker process for each CPU core allocated to the gateway. For example, allocate four CPU cores and set four workers. Do not leave the worker count to host-level auto-detection when the container has a smaller CPU allocation. See Performance Benchmark for the test methodology.
- Plan capacity for a failure. The remaining gateway instances must handle peak traffic while one instance, host, node, or availability zone is unavailable.
- Deploy at least two gateway instances. Use three or more when you need to preserve redundancy during a rolling update or a single-instance failure at peak load.
- Prepare a load balancer. Route traffic only to healthy gateway instances and test removal and re-addition of an instance before launch.
- Protect control plane connectivity. Use the mTLS credentials generated for the gateway group, restrict the DP Manager endpoint to trusted networks, and monitor certificate expiration.
- Define operational ownership. Assign owners for capacity, upgrades, certificates, database backups, alerts, and incident response.
Kubernetes and Helm Checklist
Maintain a Production Values File
- Store a dedicated production
values.yamlfile in version control. - Keep secrets out of the values file. Reference Kubernetes Secrets or your external secret manager instead.
- Retain the Dashboard-generated gateway group, DP Manager, and mTLS settings when adding production overrides.
- Review the rendered manifests with
helm templatebefore applying them. - Apply every change with
helm upgrade --install -f values.yaml. Do not edit the generated ConfigMap, Deployment, or files inside a running pod because Helm will overwrite those changes. - Record the chart version with the values file so upgrades are reproducible.
The following example provides a production baseline for a gateway release named api7-ee-3-gateway. Adjust the CPU, memory, replicas, image tag, and scheduling rules based on your load test and cluster topology.
apisix:
kind: Deployment
replicaCount: 3
image:
repository: api7/api7-ee-3-gateway
tag: "<gateway-version>"
resources:
requests:
cpu: "4"
memory: 8Gi
limits:
cpu: "4"
memory: 8Gi
terminationGracePeriodSeconds: 300
podDisruptionBudget:
enabled: true
minAvailable: 2
topologySpreadConstraints:
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: ScheduleAnyway
labelSelector:
matchLabels:
app.kubernetes.io/name: gateway
app.kubernetes.io/instance: api7-ee-3-gateway
- maxSkew: 1
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app.kubernetes.io/name: gateway
app.kubernetes.io/instance: api7-ee-3-gateway
nginx:
workerProcesses: "4"
workerShutdownTimeout: 240s
api7ee:
status_endpoint:
enabled: true
ip: 0.0.0.0
port: 7085
gateway:
readinessProbe:
httpGet:
path: /status/ready
port: 7085
initialDelaySeconds: 5
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
livenessProbe:
httpGet:
path: /status
port: 7085
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
updateStrategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 0
maxSurge: 1
If you use a different Helm release name, update app.kubernetes.io/instance in both topology spread constraints. Confirm that the nodes have the topology labels used by the constraints. If the cluster does not span availability zones, omit the zone constraint.
The example sets equal CPU and memory requests and limits to provide a predictable starting point. This qualifies the gateway container for the Kubernetes Guaranteed quality-of-service class when all containers in the pod meet the same requirements. If your organization deliberately uses a burstable policy, keep the CPU request at or above the planned worker count. Set an intentional limit and verify latency under CPU contention. Do not copy the example sizing without a representative load test.
Verify Availability and Scheduling
- Set
apisix.replicaCountto at least2; use3or more for stricter availability requirements. - If HPA is enabled, set
autoscaling.minReplicasto the required HA floor. The chart ignoresapisix.replicaCountwhile HPA is enabled. - Spread replicas across nodes and, where available, zones. Confirm the running placement with
kubectl get pods -o wide. - Enable a PodDisruptionBudget that permits maintenance without removing too many replicas. Ensure the budget still allows planned node drains.
- Use a rolling update strategy that keeps sufficient capacity available throughout an upgrade.
- Size the cluster for both the gateway requests and the temporary
maxSurgepods created during a rollout. - Use dedicated or appropriately isolated nodes for latency-sensitive workloads. Avoid burstable node types for sustained high throughput.
Verify Resources and Gateway Workers
- Use whole CPU cores for the initial gateway allocation and set
nginx.workerProcessesto the same number. - Set memory requests and limits from measured steady-state and peak usage, including the plugins and shared dictionaries you enable.
- Monitor CPU throttling, memory working set, out-of-memory terminations, pod restarts, and request latency.
- When HPA scales on CPU utilization, remember that utilization is calculated against the CPU request. Load test the target and scale-down behavior.
- Revisit worker, CPU, memory, and replica settings together. Changing only one can create contention or unused capacity.
Verify Lifecycle and Networking
- Use
/statusfor liveness and/status/readyfor readiness. See Configure Readiness and Liveness Probes. - Keep status port
7085and metrics port9091private to the cluster, monitoring system, and load balancer. - Set
terminationGracePeriodSecondslonger than the pre-stop delay plusnginx.workerShutdownTimeout, especially for long-lived or streaming requests. - Test pod deletion and node drain while sending traffic. Confirm that readiness removes a terminating pod before its connections are closed.
- Choose the gateway Service type, load balancer annotations, source IP policy, and allowed source ranges explicitly for your environment.
- Apply NetworkPolicies or equivalent controls so only required clients, upstreams, monitoring systems, DNS, and DP Manager endpoints are reachable.
Deploy and Verify
Render and review the manifests:
helm template api7-ee-3-gateway api7/gateway \
--version "~3.10.0" \
-n api7 \
-f values.yaml > rendered.yaml
Apply the release and wait for it to become healthy:
helm upgrade --install api7-ee-3-gateway api7/gateway \
--version "~3.10.0" \
-n api7 \
--create-namespace \
--atomic \
--wait \
-f values.yaml
Verify the resources and placement:
kubectl get deployment,pods,pdb,service -n api7 -o wide
kubectl top pods -n api7
kubectl rollout status deployment/api7-ee-3-gateway -n api7
Do not commit rendered.yaml if it contains rendered credentials or other sensitive values.
Docker Compose Checklist
Docker Compose manages a set of containers consistently on one host. It does not reschedule containers to another host when the host fails and does not perform a multi-host rolling update.
Externalize Configuration
- Create a dedicated deployment directory containing the Compose file, a
gateway_conf/config.yamloverride, and host directories for persistent gateway data. - Mount
config.yamlat/usr/local/apisix/conf/config.yamlas read-only. Verify the source path is a file before starting Compose. - Keep the Dashboard-generated connection and mTLS values in a host-protected environment file or secret manager. Do not commit or print rendered secrets in build logs.
- Persist
apisix.uidoutside the container so recreating the container does not register it as a new gateway instance. - Pin the image version in the Compose
.envfile or Compose file. - Back up the Compose file, gateway configuration, and UID file, and review all changes before recreating the container.
Configure the worker count and status endpoint in the host-managed file:
apisix:
status:
ip: 0.0.0.0
port: 7085
nginx_config:
worker_processes: 4
worker_shutdown_timeout: 240s
The worker count in this example matches the four CPU cores allocated in the Compose service below.
Set values used for Compose interpolation in .env next to compose.yaml:
GATEWAY_VERSION=<gateway-version>
GATEWAY_STATUS_BIND_IP=127.0.0.1
Copy the gateway group and mTLS values from the Docker command generated by the Dashboard into gateway.env. The following file shows the expected format:
API7_CONTROL_PLANE_ENDPOINTS='["https://<dp-manager-host>:7943"]'
API7_GATEWAY_GROUP_SHORT_ID=<gateway-group-short-id>
API7_CONTROL_PLANE_CERT='-----BEGIN CERTIFICATE-----
<gateway-client-certificate>
-----END CERTIFICATE-----'
API7_CONTROL_PLANE_KEY='-----BEGIN PRIVATE KEY-----
<gateway-client-private-key>
-----END PRIVATE KEY-----'
API7_CONTROL_PLANE_CA='-----BEGIN CERTIFICATE-----
<control-plane-ca-certificate>
-----END CERTIFICATE-----'
Keep the PEM values single-quoted so Docker Compose preserves their line breaks. Replace each placeholder with the complete value from the generated command.
Create the persistent UID file and host log directory before starting the gateway. The UID bind-mount source must already be a file; otherwise, Docker can create a directory at that path. Ensure that the user running inside the gateway container can write to gateway_logs.
mkdir -p gateway_data gateway_logs
test -s gateway_data/apisix.uid || uuidgen > gateway_data/apisix.uid
chmod 600 gateway.env
chmod 644 gateway_data/apisix.uid
Generate a different UID on each gateway host. Reuse a UID only when recreating the same gateway instance; do not copy it to another concurrently running instance.
Manage the Gateway with Compose
Use the Docker command generated by the Dashboard as the source for gateway group and mTLS environment variables, then move those values into the Compose deployment. A production-oriented gateway service can use the following pattern:
services:
gateway:
image: api7/api7-ee-3-gateway:${GATEWAY_VERSION}
restart: unless-stopped
cpus: "4.0"
mem_limit: 8g
env_file:
- ./gateway.env
volumes:
- ./gateway_conf/config.yaml:/usr/local/apisix/conf/config.yaml:ro
- ./gateway_data/apisix.uid:/usr/local/apisix/conf/apisix.uid:ro
- ./gateway_logs/:/usr/local/apisix/logs/:rw
ports:
- "9080:9080"
- "9443:9443"
- "${GATEWAY_STATUS_BIND_IP:-127.0.0.1}:7085:7085"
ulimits:
nofile:
soft: 65536
hard: 65536
healthcheck:
test: ["CMD-SHELL", "wget -q -O- http://127.0.0.1:7085/status/ready >/dev/null 2>&1 || exit 1"]
interval: 10s
timeout: 5s
retries: 3
start_period: 10s
stop_grace_period: 5m
logging:
driver: json-file
options:
max-size: 100m
max-file: "5"
Use the exact gateway group, DP Manager, certificate, and key values generated by the Dashboard. Restrict gateway.env to the account that operates API7 Gateway. Be careful when running docker compose config: its output can contain the resolved secret environment values.
The logging limits above prevent the default local JSON logs from growing without bounds. If you use a centralized logging driver or agent, replace this section with the settings required by that system.
Store Gateway Logs on the Host
The Compose logging section rotates only the container output captured from standard output and standard error. API7 Gateway writes its access and error logs to /usr/local/apisix/logs/ by default. The gateway_logs bind mount above stores those files in the host deployment directory without requiring additional log-path settings in gateway_conf/config.yaml.
To rotate the files stored in that directory, enable the built-in log-rotate plugin and merge the following settings into the existing plugin_attr section in gateway_conf/config.yaml:
plugin_attr:
log-rotate:
enable: true
timeout: 10000
interval: 3600
max_kept: 168
max_size: 104857600
enable_compression: false
Also enable log-rotate in the existing plugins list shown in the configuration reference. Preserve all existing plugin names: setting plugins to only log-rotate disables the other plugins.
The plugin rotates access.log and error.log inside the mounted directory. Adjust the interval, retained-file count, maximum file size, and compression setting for your retention requirements, and continue to monitor host disk usage.
Verify the Host and Container
- Reserve CPU and memory for the host operating system, Docker daemon, monitoring agent, and load balancer agent. Do not allocate every host core to the gateway container.
- Set
cpusandmem_limit; Docker containers have no resource limits by default. - Match
nginx_config.worker_processesto the Compose CPU allocation and validate the result with a load test. - Set the container
nofilelimit above the configured NGINX worker connection requirements and verify the host kernel limit is sufficient. - Configure a restart policy and confirm Docker starts automatically after a host reboot.
- Send logs to a bounded local driver or centralized logging system and monitor disk usage.
- Keep the Docker socket and deployment files accessible only to trusted operators.
- Expose only the proxy ports publicly. Restrict the status, metrics, DP Manager, Dashboard, and database ports to trusted networks.
Validate and start the deployment:
docker compose config --quiet
docker compose pull
docker compose up -d
docker compose ps
docker compose logs --tail=100 gateway
docker stats --no-stream "$(docker compose ps -q gateway)"
Confirm that the container is healthy and the gateway accepts traffic:
curl -i "http://127.0.0.1:7085/status"
curl -i "http://127.0.0.1:7085/status/ready"
curl -i "http://127.0.0.1:9080/"
A 404 response from port 9080 is expected before you configure a matching route.
Provide Multi-Host High Availability
- Run the same pinned Compose deployment on at least two independent Docker hosts.
- Place the hosts in different failure domains when the infrastructure supports it.
- Put an external load balancer in front of the gateway hosts and configure HTTP health checks against
/statusor/status/readyon port7085. - Ensure the surviving hosts can handle peak traffic when one host is unavailable.
- Drain one gateway host from the load balancer before an upgrade, wait for connections to complete, update and verify it, return it to service, and then continue with the next host.
- Test a full host failure. A container restart policy only handles process or daemon recovery on the same host.
Do not use multiple replicas on one Docker host as the only HA measure. The host, Docker daemon, network interface, and storage remain shared failure points.
Security and Operations Checklist
- Terminate client-facing TLS with certificates managed through a documented renewal process.
- Use TLS to upstream services when required by your threat model and verify upstream certificates.
- Do not expose the data plane Admin API to untrusted networks. Keep it disabled unless a documented workflow requires it.
- Restrict Dashboard, DP Manager, database, metrics, and status endpoints to the smallest required network scope.
- Export gateway metrics and logs, and alert on availability, error rate, latency, CPU saturation or throttling, memory pressure, restarts, and control plane connectivity.
- Back up the control plane database and regularly test restoration. Gateway replicas do not replace control plane backups.
- Document upgrade and rollback commands, the last known-good image and values, and the operator responsible for rollback decisions.
- Run a pre-production load test and failure test with the same deployment configuration used in production.
- Verify that one replica or host can be removed without breaching the latency and error-rate objectives.
- Review capacity and configuration after material traffic, route, plugin, payload, or logging changes.
Final Go-Live Checks
- All gateway instances report healthy in the API7 Dashboard.
- The load balancer sends traffic only to ready instances.
- The configured worker count matches the CPU allocation for every gateway instance.
- Kubernetes replicas are distributed across the intended nodes or zones, or Docker replicas run on independent hosts.
- Resource dashboards and alerts are active and have been tested.
- Certificate expiration alerts, database backups, upgrade procedures, rollback procedures, and incident contacts are documented.
- A production smoke test verifies the critical routes, authentication, rate limits, TLS, upstream connectivity, logging, and metrics.