Why teams manage Apache APISIX configuration as code with ADC
When routes, consumers and plugins are changed through the Admin API or a dashboard, the gateway slowly stops matching the configuration in Git. A route that works in staging may carry a different rate limit in production, and nobody can say which change was intended. ADC (API Declarative CLI) keeps the gateway's configuration in files you review, and it syncs those files to the APISIX or API7 Enterprise Admin API. A team needs it once more than one environment exists, more than one person changes the gateway, or an audit asks who changed a route and why.
ADC is Apache-2.0 licensed and published by API7. It works with both Apache APISIX and API7 Enterprise Admin APIs and offers the commands ping, dump, diff, sync, lint and convert openapi. In practice, dump captures the live state as a starting point, diff shows what a change would do before anything is applied, lint checks the files before review, and sync applies them. Before adopting it, confirm which APISIX version your environments run and that the ADC release you choose supports it, since the Admin API behavior around defaults has changed between releases.
DeployOpen plans and implements this workflow inside your environment: the repository layout, the CI pipeline that runs lint and diff on each change, the promotion path between environments, and the controls over who can approve a sync. The gateway, its Admin API credentials and the pipeline runners stay in infrastructure you control. Before work starts, confirm with your team which environments exist today, whether any routes were created by hand and must be captured first, and who is authorized to run sync against production.
What each ADC command does in the delivery workflow
The ping command is the first check in any pipeline. It confirms that ADC can reach the target gateway and that the credentials it uses are accepted by the Admin API before any other step runs. In a CI job, a failed ping should stop the pipeline immediately, because later steps would otherwise report misleading errors about files or diffs when the real problem is connectivity or authentication.
- Connectivity check: confirms the network path from the runner to the Admin API endpoint of the target environment.
- Credential check: confirms the Admin API key or token the job supplies is accepted, which keeps secrets in the CI secret store rather than in the repository.
- Per-environment targets: run it once for each environment, such as development, staging and production, so a promotion job cannot silently point at the wrong gateway.
- Fail-fast placement: place it at the start of every job that reads or writes gateway state.
- Version awareness: confirm the Admin API version and ADC version pairing for your APISIX release, since the supported combinations are listed in the ADC repository.
Check that your pipeline treats a failed ping as a hard stop and that each environment has its own credentials and target definition.
The dump command captures the current configuration of a live gateway and writes it to files. Teams use it to bring an existing, hand-managed gateway under version control and to refresh the repository after an emergency change made through the Admin API or dashboard. The output is the baseline for every later diff, so the quality of the first dump determines how much noise your reviews will carry.
- Initial import: produces the first set of files for routes, services, consumers and plugin configuration that an existing gateway already serves.
- Emergency capture: records changes made outside Git so they can be reviewed and folded into the repository rather than being lost on the next sync.
- Defaults in output: check whether the dumped files include fields the Admin API filled in automatically, because those fields later appear as differences.
- Secrets review: inspect the dump for credentials, keys and sensitive plugin values before committing, and move them to the secret store.
- Scope control: confirm which resource types and selectors the command includes so you know what the repository actually covers.
Confirm the exact flags, output layout and file format for your ADC version in the ADC repository before you rely on a dump as the source of truth.
The diff command compares the files in the repository with the configuration on the live gateway and reports what would change. It is the main drift detector in the loop. A clean diff means the repository and the gateway agree. A non-empty diff means either someone changed the gateway outside Git or the repository has a change that has not been applied yet. In review, the diff output is what approvers should read, not the pull request text alone.
- Pull request evidence: attach the diff output to the merge request so reviewers see the exact resources that will change.
- Drift detection: run it on a schedule against production to find manual edits made through the Admin API or dashboard.
- Noise from defaults: when the gateway fills in default values that the files do not contain, a diff can show changes that do nothing. Treat unexpected changes on untouched resources as a signal to investigate.
- Plugin configuration changes: review plugin blocks closely, since a small edit can change authentication or rate limits for every route that uses the plugin.
- Exit behavior: confirm how the command signals a difference to CI, so a pipeline can fail or pause on unexpected drift.
Check that a diff on an unchanged repository returns no changes in each environment, because a permanent diff usually points to a defaults or formatting mismatch.
The lint command checks the configuration files before anything reaches a gateway. It runs without changing live state, which makes it suitable for pre-merge checks on every pull request. Lint catches structural and rule-level problems early, such as malformed resources or settings that the tool can identify as invalid, so reviewers spend their time on intent rather than syntax.
- Pre-merge gate: run it on every merge request so invalid files cannot reach the default branch.
- Structural validation: catches malformed or incomplete resource definitions before a sync attempt.
- Consistent style: applies the same checks to every author, which reduces variation in how routes and plugins are written.
- Local runs: let engineers run the same check on a workstation before pushing, which shortens feedback time.
- Scope limits: lint validates the files, not the behavior of the upstream services or whether a route will match real traffic, so it complements rather than replaces tests.
Confirm which rules lint enforces in your ADC version and add any organization-specific checks, such as naming conventions, in a separate step.
The sync command applies the files in the repository to the target gateway, and convert openapi generates starting resources from an OpenAPI 3 document. Sync is the only step that writes live state, so it belongs in a controlled promotion job with approvals. Convert openapi is an authoring aid: it produces draft routes that teams then refine by adding plugins, upstreams and access rules. Keep the generated output in Git so the OpenAPI source and the gateway configuration stay traceable to each other.
- Controlled apply: run sync only from a protected branch or a promotion job, using credentials scoped to that environment.
- Dry-run first: check whether your ADC version offers a preview mode, and review it before applying to production.
- Starting resources: use convert openapi to draft routes from an OpenAPI 3 document, then edit the output and commit the edits.
- Spec and config drift: when the API specification changes, regenerate or update the routes and review the diff, since a spec change does not update the gateway by itself.
- Ordering in CI: run ping, lint and diff before sync, so the apply step only runs on validated, reviewed changes.
Confirm the exact sync and convert flags, supported OpenAPI features and the behavior of each mode in the ADC repository for the version you deploy.
Why the Admin API default-value behavior breaks ADC diffs
The Admin API fills in default values when it stores a resource, so the copy APISIX holds can differ from the file in your Git repository even when nobody has changed anything. The APISIX Ingress Controller 2.0 upgrade guide notes this behavior and warns that because of it, ADC diffs can break and trigger full data plane updates. A diff tool compares your declared routes, services, consumers and plugins against what the gateway returns. If the gateway returns fields you never wrote, every resource can look changed, and a sync then rewrites the whole configuration instead of the one route you edited.
The APISIX changelog records that APISIX 3.14.0 stopped the Admin API from populating default values when writing resources. Before you rely on a no-op diff, confirm which APISIX version your gateways and any Ingress Controller deployment run, because the behavior you see depends on that version. Check the version in your deployment manifests and in the running containers or packages, not only in your plan. Upgrading across the 3.14.0 boundary can change how existing resources compare, so treat it as a change that needs a diff check.
After every APISIX upgrade, run ADC diff against an unchanged configuration in a non-production environment and confirm it reports no changes. If it reports changes, read them before running sync, since a sync may push default fields back into every resource. Record the result in the change ticket so the next upgrade has a baseline. If you run an older APISIX release, plan the upgrade path first and ask your implementation partner to confirm how ADC and the Ingress Controller version pair for your environment.
How to set up ADC sync in CI for APISIX
This sequence moves APISIX gateway configuration from manual Admin API edits into a Git-reviewed pipeline, where every change is previewed as a diff before ADC applies it. The result is a repository that matches the live gateway, with a check at each step that shows the pipeline is trustworthy.
Pin the APISIX and ADC versions
The platform team records the exact APISIX gateway version and the ADC release in the pipeline configuration and in the repository README, so every run uses the same tool behavior. Pinning matters because ADC diffs depend on how the Admin API fills in defaults, and the APISIX 3.14.0 change to stop populating defaults affects what a diff reports. Confirm the pairing against the ADC repository and the APISIX changelog before you pin. The step is done when a pipeline run prints both versions and the ADC version is set in one file that reviewers can change only through a pull request.
Export a baseline with dump
An engineer with Admin API access runs ADC dump against the existing gateway to capture routes, services, consumers, upstreams and plugin configuration as files. The export is a starting point and usually needs cleanup, such as removing generated IDs, secrets that should come from a vault, and objects created by other tools. Store the baseline on a branch for review. The check is that a second dump from the same unchanged environment produces no file changes, which shows the export is stable.
Commit files with one layout per environment
The team commits the exported files to Git using a directory per environment, for example one for development, one for staging and one for production, with shared configuration kept in a common location. Environment-specific values such as upstream hosts and plugin settings stay in the environment directory. Reviewers approve the layout once, and the repository becomes the only place where desired state is written. The check is that each environment directory yields a diff against its own gateway that contains only the expected environment differences.
Add a lint and diff job that fails on unexpected changes
The pipeline runs ADC lint and then ADC diff for each environment on every merge request, with no changes applied. The job fails when lint reports errors or when the diff contains changes the author did not intend, such as resources the repository does not declare or plugin settings that would be rewritten with defaults. The team should review the diff output in the job log and in the merge request. The check is that a no-change merge request on a clean environment completes with an empty diff.
Add a protected sync job with approval
A separate job runs ADC sync only on the main branch, after the lint and diff job has passed and a named approver has signed off on the production environment. The job reads the Admin API key from the CI secret store rather than from the repository, and the runner is restricted to the pipeline's service account. Confirm with your security team which approval and audit rules apply to production gateway changes. The check is that a merge to the main branch without approval does not reach the sync stage, and the job log records who approved it.
Run a no-op diff after the first sync
Immediately after the first successful sync, the pipeline runs ADC diff again against the same environment. Because the gateway now matches the repository, the expected result is an empty diff. If the diff is not empty, the cause is usually a default value written by the Admin API or a field the repository does not model, and the team must resolve it before the next change. The check is an empty diff recorded in the job log, which becomes the baseline for later runs.
Schedule drift detection
The team adds a scheduled pipeline that runs ADC diff against each environment at a cadence the platform owner sets, and it alerts the owning team when the diff is not empty. Drift usually comes from manual Admin API changes, emergency fixes or another automation writing to the gateway. The alert should link to the diff output so the owner can either commit the change to Git or revert it on the gateway. The check is a deliberately made manual change in a non-production environment that the scheduled job reports within the next run.
Environment promotion and drift detection choices
Every ADC pipeline has to answer the same questions: how stages differ, how a change moves between them, and how the team learns that someone changed the gateway by hand. The cards below cover the choices that most affect safety, and each one is worth settling in writing before the first production sync.
Directory per stage or variables per stage
You can keep one directory per environment, each with its own copy of the route and plugin files, or one shared set of files with variables that change per stage. Separate directories make each stage easy to read but invite copy drift between them. Shared files with variables keep the logic in one place, but a bad variable can reach production unnoticed. Whichever you pick, run a diff between two stages in CI and check that the only differences are the ones you intended.
Promoting the same commit
Promotion works best when staging and production sync the same Git commit, not a rebuilt configuration. Tag or record the commit that passed staging, then have the production job check out that exact revision. Ask who approves the promotion and whether a rollback means re-syncing an earlier commit. Confirm that the pipeline stores the commit ID alongside each sync so an audit can tie a live gateway state back to a reviewed change.
Secrets and upstream addresses per environment
Upstream hosts, consumer credentials and plugin secrets differ between stages, and they should never be committed in plain text. Inject them at sync time from your CI secret store or a vault, and keep only placeholders in the repository. Check how each secret reaches the ADC process, because environment variables visible in CI logs are a common leak path. Make sure a missing variable fails the job instead of syncing an empty value into the gateway.
Detecting manual Admin API edits
Someone with an Admin key can still change routes in the console or with curl, and those edits never appear in Git. Run a scheduled dump of the live gateway and diff it against the repository, then alert on any difference. Decide in advance whether the next sync should overwrite manual edits or stop for review. Treat repeated drift as a process problem, and restrict who holds the Admin key so the schedule catches the exceptions that remain.
Limiting who can sync production
A sync against production changes live traffic, so the job that runs it needs tighter controls than the job that runs lint or diff. Use protected branches, required reviewers, and a production environment with its own approval step in your CI system. Confirm that the Admin key used by the production job is separate from the one used in lower stages. Record who approved each run so you can answer that question during an incident or assessment.
Resources owned by the Ingress Controller
Routes and consumers created from Kubernetes resources are managed by the APISIX Ingress Controller, which overwrites changes made through the Admin API or through ADC. Keep those resources out of the ADC scope, or move them into Kubernetes manifests entirely. Mixing the two owners on one route is the most common source of flapping configuration. Check the ownership boundary in writing before enabling any scheduled sync.
Configuration options and when each fits
This table compares the main ways to manage APISIX routes, services, consumers and plugins, from direct Admin API calls to ADC in CI with per-environment repositories. Read each row against your team size, change frequency and how many environments you promote through. The main takeaway is that ADC in CI with a dump-based baseline gives the most review and drift control, but only after the team confirms its diffs stay clean on the APISIX version in use.
| Option | Fits when | Trade-offs |
|---|---|---|
| Admin API called directly | A single small team makes occasional changes and one environment is enough | No review trail or diff before writes, and drift from Git goes unnoticed until someone looks |
| ADC run by hand | A team is moving off manual edits and wants a declarative diff before each sync | Results depend on who runs it and from which workstation, so the same change can land differently |
| ADC in a CI pipeline | Several people change routes and plugins and every change needs review and a recorded sync | Pipeline credentials for the Admin API must be scoped and rotated, and the pipeline needs its own test environment |
| Dump-based baseline | An existing gateway already holds routes and plugins that must be brought under Git without rebuilding them by hand | The first dump captures live state, including defaults and drift, so it must be reviewed before it becomes the source of truth |
| Hand-written files from scratch | A new API is being designed and no live state needs to be preserved | Errors reach production unless lint and diff run before sync, and authors must know the exact schema |
| Separate repository per environment | Environments differ in governance, access or networks, and each team owns its own gateway | Shared changes must be copied between repositories, which invites divergence over time |
| One repository with environment overlays | Environments share most configuration and differ only in upstreams, hosts or secrets | Overlay logic adds review burden, and a mistake in a shared file reaches every environment at once |
Securing the Admin API credentials and sync pipeline
A config-as-code pipeline is only as safe as the credential that can change the gateway. The cards below cover where the Admin API key lives, who and what can use it, how changes are reviewed and recorded, and how the Admin port is kept off untrusted networks.
Admin API key in the CI secret store
The sync job needs the Admin API key to write routes, consumers and plugins, so the key should live only in the CI system's secret store and be injected at run time. Never place it in the repository, in ADC configuration files or in dump output. Check that job logs mask the value and that the key is rotated on a schedule your security team sets.
Least-privilege access for the sync job
Give the sync pipeline its own credential rather than the administrator key used by people. Ask which Admin API operations the key can perform and whether your deployment can separate read-only access used by dump and diff from write access used by sync. Use one credential per environment so a staging job cannot write to production.
Protecting the main branch
Because a merge to main drives a sync to production, the branch is the real change control point. Require pull request review from people who did not author the change, block direct pushes, and require the lint and diff checks to pass before merge. Confirm that repository administrators cannot bypass these rules without a recorded exception.
Audit trail of applied changes
Record who approved each change, which commit was applied and what the diff showed at the time of sync. Keep the CI run logs and the Git history together so an auditor can trace a live route back to a reviewed commit. Confirm with your team how long CI logs are retained and whether they are stored outside the pipeline system.
Keeping the Admin port private
The Admin API listens on a separate port from client traffic, so it should never be exposed to user networks or the internet. Restrict it to the sync runner's network path and to operators' management subnets, and confirm the firewall or security group rules after each deployment. Verify the port numbers against your version of the deployment modes documentation.
Questions teams ask before managing APISIX configuration as code
Can our team run ADC for APISIX without an outside partner?
Yes, a capable platform or API team can adopt ADC on its own, since the tool is open source under the Apache-2.0 license and published by API7. The work is mostly engineering discipline: exporting the current state, storing it in Git, writing a pipeline that runs lint, diff and sync, and agreeing who may approve changes. Teams that have not yet worked with Admin API resources, CI runners or environment promotion usually find the first few weeks slower than expected. A partner is useful when the team wants the pipeline and review process designed and handed over in a fixed scope, with the decisions written down.
What drives the effort of moving APISIX configuration into code?
The main drivers are the number of routes, services, consumers and global rules, how many plugins each route carries, how many environments must match, and how much configuration was created by hand in the Admin API or dashboard. Three other factors matter as much: how mature the CI system already is, whether anyone owns the gateway's current state, and how many teams change routes independently. A small, well-documented gateway with one environment is a short exercise. A large estate with shared plugin configuration across several clusters is not. Ask for the scope to list each of these counts before agreeing a fixed price.
How long does a migration from manual configuration usually take?
No general duration is published for this work, so treat any figure you hear with caution and ask for one tied to your inventory. The time depends on how many resources exist, how far the live state has drifted from documentation, how many environments need promotion, and whether the team must first clean up default values. Each environment also needs a dump, a diff against the expected result and a review before the first sync. Ask for a timeline that lists each phase (inventory, export, repository layout, CI pipeline, pilot environment, production cutover) and the decisions the client must make at each one.
What does the work need from our side?
You will need a Git repository with branch protection, a CI runner that can reach the APISIX Admin API in each environment, and an Admin API key kept in the CI secret store rather than in the repository. Named owners matter as much as access: someone must approve changes to routes and plugins, someone must own the consumer and credential model, and someone must be able to accept or reject a diff that touches production. Expect to provide test upstreams for a staging environment and a window for a controlled cutover. Confirm these items with your platform and security teams before the scope is fixed.
How do we avoid a full data plane update caused by default values?
The APISIX Ingress Controller 2.0 upgrade guide notes that the Admin API fills in default values, so a diff between your Git files and the live state can show changes that do not exist in your intent. When that happens, the sync can trigger a full data plane update. The practical controls are to confirm your APISIX version, since APISIX 3.14.0 stopped the Admin API from populating defaults when writing resources, to run a dump and diff on each environment before the first sync, and to review every planned change that touches an unexpected field. Ask any partner to show a diff from a non-production environment before production work begins.
Why does a diff show changes we never made?
Usually because the live gateway holds fields that your files omit, such as defaults the Admin API writes into a resource. ADC compares your declared resources with what the gateway reports, so a missing field can look like a removal or a change. Before you sync, run a dump to capture the live state, compare it with the repository, and decide for each field whether to declare it or accept the default. Normalizing the files once, and keeping that normalized format in lint checks, reduces noise in later reviews.
What should a quote for this work include?
A quote should state the written scope: the APISIX and ADC versions covered, the number of gateways and environments, the resource inventory used as the baseline, and the repository layout and CI platform. It should list each deliverable, such as the exported baseline, lint and diff rules, the sync pipeline, the promotion procedure, drift detection and handover documentation. It should separate one-time work from recurring work, name any retainer for upgrades or support, and state what the client must provide. Ask how changes after scope approval are handled and what acceptance criteria close the engagement.
Does configuration as code replace the need for change review?
No. Storing routes, plugins and consumers in Git gives you history and a place to review changes, but the review still needs an owner who understands the traffic impact of each route and credential change. Pair the repository with branch protection, required approvals for production paths, lint checks and a dump-based drift check that runs on a schedule. The Git history then becomes the audit trail for the gateway configuration.
How DeployOpen delivers configuration as code for APISIX
DeployOpen plans and implements the ADC workflow inside your own infrastructure, so the routes, services, consumers and plugins for your APISIX gateway are kept in Git and synced by your pipeline from the start. The work begins with a written scope that names the APISIX version and deployment mode, the Admin API endpoints the pipeline will call, the environments to promote through, and the approval points for production changes. Because most engagements are fixed-scope, the deliverables and timelines are agreed in writing before any build work starts, and the quote follows from that scope rather than from a list price.
The handover is built around the repository layout and runbooks that your team will use after go-live. DeployOpen documents how the dump, diff, lint and sync steps are wired into CI, how environment-specific values are separated from shared route definitions, how drift is detected and who acts on it, and how a default-value change in a newer APISIX release is reviewed before it reaches the data plane. Confirm early which ADC and APISIX versions your team will pin, since the upgrade guide and changelog behavior described above affect how the diff baseline should be captured and refreshed.
Ongoing support, upgrades and continuous checks of the configuration pipeline can be covered by a retainer, which suits teams that will keep changing routes after the first rollout. Ask any delivery partner, including DeployOpen, to state in the quote which items are one-time (repository design, pipeline build, initial dump and migration of existing configuration) and which recur (version upgrades, review of diffs, drift reports and access changes). DeployOpen prepares the systems, documentation and evidence for your reviews, but it does not issue audit reports or certifications; those come from independent assessors.

