GitOps
Drive AISIX configuration from Git — a validate-ship-reload pipeline for the open-source resources.yaml gateway, and an Admin API apply-and-verify pipeline for AISIX Enterprise.
AISIX configuration can be version-controlled in Git and delivered through a CI/CD pipeline, but the pipeline you build depends entirely on which product you run. The open-source AISIX gateway and AISIX Enterprise disagree about where configuration lives, so they disagree about what a pipeline pushes and how it confirms success.
- Open-source AISIX gateway: configuration is a file the gateway process reads. A pipeline ships that file and reloads the process.
- AISIX Enterprise: configuration is control-plane state, projected asynchronously to connected gateways. A pipeline calls an API and then polls for projection to finish.
Pick the track that matches your deployment. Running gateways connected to AISIX Enterprise alongside a standalone open-source gateway means running both pipelines, each against its own resources.
Track A: Open-Source AISIX Gateway
This track applies to a gateway with no control plane, configured through a declarative resources.yaml file.
How AISIX Loads Configuration
Three properties of the load model shape everything else in this pipeline:
- One file, no includes.
resources_filenames exactly one path. AISIX does not load a directory, and it does not resolve include or import directives. If your source is split into multiple documents, something outside AISIX has to assemble them into one YAML document before it reaches the gateway. - Full-snapshot replace. A successful load does not merge with the previously active configuration — it replaces it. A collection or entry missing from the file you ship is gone from the running gateway, not left alone.
- Explicit reload only. AISIX does not watch
resources.yamlfor changes. The file is read at process startup and re-read only when the process receivesSIGHUP. A file edited on disk with no reload trigger changes nothing.
See Resources File Reference for the complete format and Configuration Propagation for the reload mechanics this pipeline automates.
Repository Layout
Store one complete resources.yaml at the repository root — or wherever your build tooling expects it — matching the file AISIX actually loads:
aisix-config/
├── resources.yaml
└── README.mdA single file is the layout that needs no assembly step and can't drift from what the gateway loads.
If your team prefers reviewing smaller diffs, you can instead keep the source split into one fragment per collection:
aisix-config/
├── fragments/
│ ├── provider_keys.yaml
│ ├── models.yaml
│ ├── api_keys.yaml
│ └── guardrails.yaml
└── resources.yaml # generated by CI, not hand-editedTreat fragments/ as a CI-only convenience. AISIX never reads it — only the assembled resources.yaml is a valid load target. Name fragments after real collections from the Resources File Reference (provider_keys, models, api_keys, guardrails, passthrough_routes, and so on); there is no routes collection, so don't structure fragments around one.
CI: Validate
Run aisix validate against the assembled file on every change, before merge:
aisix validate --resources resources.yamlvalidate runs the identical load pipeline the gateway uses — parsing, ${VAR} interpolation, name-reference resolution, schema validation, and cross-reference checks — without starting a listener, so a clean exit means the file will load. Run it with the same environment variables the target gateway will have, since ${VAR} references resolve against whatever environment the validate process sees. Treat a non-zero exit as a merge blocker.
CD: Assemble, Ship, Reload
On merge, or on promotion to each environment:
-
Assemble. If you keep fragments, concatenate them into the complete
resources.yamlyour target gateway will load. Re-runaisix validateagainst the assembled result — CI validated a fragment set, not necessarily the exact bytes about to ship. -
Ship the file. Deliver it to wherever the gateway's
resources_filesetting points — the mounted path in a container image, a volume, a config map, or a file synced onto the host. -
Trigger a reload. Send
SIGHUPto the running process, or perform a rolling restart that boots each replacement instance with the new file already in place. AISIX does not pick the file up on its own. -
Confirm. Query the metrics and status listener and check that
stateissyncedandapply_seqadvanced:curl -sS "http://127.0.0.1:9090/status/config"See Confirm the Applied Configuration for the full check, and follow it with a caller-facing request through the endpoint that changed — a synced reload confirms the file loaded, not that the specific resource behaves as intended.
This loop is synchronous end to end: ship, reload, poll /status/config until it reflects the new snapshot, then verify with a live request. There is no separate projection step to wait on.
Rollback
Revert the Git commit and run the same pipeline forward: validate the reverted file, assemble it if you use fragments, ship it, and reload. There is no separate rollback mechanism — a rollback is a normal deployment of an older, known-good file.
One property of the reload path makes this safer than it sounds: if the reverted file is invalid for any reason, a rejected SIGHUP reload does not take the gateway down. AISIX logs the rejection, exposes it through /status/config, and keeps serving the last valid snapshot. The same is not true at a fresh boot — a gateway starting cold with an invalid file stops immediately rather than coming up empty. Validate before every reload, and treat a fresh-boot deployment (a new instance, not a running one receiving SIGHUP) as the case where a bad file has real consequences.
Track B: AISIX Enterprise
This track applies to gateways connected to an AISIX Enterprise control plane, self-hosted or API7-hosted. There is no resources.yaml to ship — configuration is control-plane state, and a pipeline changes that state through the Admin API.
Where Configuration Actually Lives
AISIX Enterprise splits resource ownership between two scopes, and a GitOps pipeline should mirror that split rather than impose a flat structure:
- Organization-owned resources — provider keys, MCP and OpenAPI-backed servers, A2A agents — belong to the account-level organization and project only to the environments they're explicitly allowed into.
- Environment-owned resources — models, caller API keys, guardrails and their attachments, cache policies, rate-limit policies, OIDC providers, claim mappings, passthrough routes, observability exporters, and MCP environment access and authentication settings — belong to one environment and project to every gateway connected to it.
- Team access policies belong to an organization through their team and project to every environment in that organization.
See Resource Projection for the complete ownership-and-projection table and How AISIX Enterprise Composes for the organization/environment scope model this is built on.
Repository Layout
Structure the repository around that same boundary instead of a fictional flat tree — one directory for organization-scoped resources, one per environment for environment-scoped resources:
aisix-config/
├── organization/
│ ├── provider-keys.yaml
│ ├── mcp-servers.yaml
│ └── a2a-agents.yaml
└── environments/
├── dev/
│ ├── models.yaml
│ ├── caller-api-keys.yaml
│ └── guardrails.yaml
├── staging/
└── prod/The files here are desired-state documents your pipeline diffs against the control plane — not a resources.yaml AISIX itself loads. Their shape is up to you; keep it close to the Admin API's own resource kinds so the apply step in CI stays a straightforward diff.
CI: Apply via the Admin API
Apply changes through the AISIX Enterprise Admin API, not a file drop. On merge, or on promotion to each environment, have CI:
- Read current state from the Admin API for the affected organization or environment.
- Diff it against the desired state stored in Git.
- Issue the matching create, update, or delete calls for what changed, authenticated with a write-scoped admin token.
There is no directory or file the control plane loads on its own — every change is a discrete API call, so the pipeline owns the diffing that a file-based reload gets for free.
CD Verification
Publication through the Admin API is asynchronous: a successful write confirms only that the control plane accepted the change, not that any gateway has applied it. This is the structural difference from Track A, where a synced /status/config after a reload is the end of the loop. Here, verification is a separate step your pipeline has to run after the apply call returns. Follow the three-step method from Resource Projection:
- Compare revisions. Query
dp_nodesfor the environment and comparestore_revisionagainst each node'sapplied_revision. A node is current once itsapplied_revisionis equal to or greater thanstore_revision. - Inspect the gateway snapshot. Query
/status/configon the gateway instance handling traffic and confirmstateissynced,applied.applied_revisionreflects the expected revision, andrejectedandpartially_compatibleare both empty. This listener defaults to0.0.0.0:9090and its routes are unauthenticated (see Ports), so it's typically not published outside the deployment. Reach it from your CI runner over a private path instead of exposing it publicly — a container attached to the same Docker network, akubectl port-forwardor in-cluster request on Kubernetes, or an internal load balancer. - Verify caller-visible behavior. Call
GET /v1/modelswith the relevant caller API key to confirm the expected alias appears, then send a real request through the endpoint that changed.
Have CI poll steps 1 and 2 until they agree, on a bounded timeout, before running step 3. A pipeline that only checks the Admin API's write response and declares success is checking acceptance, not projection.
Rollback
Revert the Git commit describing desired state and re-run the same CI apply step. Because the apply step diffs desired state against current state and issues only the matching Admin API calls, it's idempotent — applying the reverted state is not a different operation from applying any other change. There is no "redeploy a gateway" step in this track: gateways don't hold configuration locally to redeploy. They pick up the correction the same way they pick up any change, through projection, so rollback verification is the same three-step check as any other apply.
Infrastructure as Code
AISIX does not currently publish an official Terraform, Pulumi, or Crossplane provider, for either the open-source resources-file format or the Enterprise Admin API. Drive changes directly from CI instead of through an IaC provider — the aisix validate / reload loop for Track A, or direct Admin API calls for Track B. If your organization standardizes on Terraform or a similar tool elsewhere, treat these pipelines as the AISIX-specific exception until an official provider exists.
Best Practices
- Keep secrets out of the repository. Track A resolves
${VAR}references from the gateway process environment — reference provider and caller credentials by variable name inresources.yamland inject the values through your deployment tooling, never commit them. Track B resources reference credentials the control plane already holds or that your CI injects when calling the Admin API; don't store plaintext secrets in the desired-state files either way. - Use one branch per environment, or a promotion-based workflow, so a change reaches
stagingbeforeprodand the repository state for each environment reflects what's actually running there. - Tag releases so a rollback target is unambiguous, and so "what changed between these two deploys" is a diff between two tags.
- Record every change. Track B has a real audit trail for this: the AISIX Enterprise control plane logs control-plane state changes separately from gateway request traffic. See Logging and Auditing for what the audit log captures. Track A has no equivalent inside AISIX itself — rely on your Git history and CI logs as the record of what was deployed and when.
Related
Track A
- Resources File Reference — the file format, load model, and every supported collection.
- Configuration Propagation — the reload cycle and how to confirm an applied change in detail.
- CLI Reference —
aisix validatesyntax, exit codes, andaisix export.
Track B
- Resource Projection — ownership and projection scope, and the three-step verification method.
- AISIX Enterprise Admin API — the API surface CI calls to apply changes.
- Resource Model — how caller API keys, models, and provider keys relate across both products.