Restricting API access by consumer in Apache APISIX

Apache APISIX can allow or deny calls per consumer on each route using the consumer-restriction and acl plugins. This page explains how to design, configure and test those rules before rollout.

On this page

How Apache APISIX restricts API access by consumer

Teams usually need consumer-level restriction when several applications, partners or machine clients share the same gateway routes, and not all of them should reach every route. In Apache APISIX, the caller is identified as a consumer by an authentication plugin such as key-auth, jwt-auth or hmac-auth. The consumer-restriction or acl plugin then allows or denies that consumer on a specific route. The decision is made per consumer, so an internal reporting client can reach /reports while a partner key is refused on that same path.

This control is different from ip-restriction, ua-restriction and referer-restriction. Those plugins examine the network address, user agent or referer of the request, which callers can share, spoof or change. A consumer rule expresses who the client is, so it survives a change of network, proxy or device. The trade-off is dependency: consumer restriction only works after an authentication plugin has identified the consumer. On a route without authentication, there is no consumer to match, so the rule cannot protect that route. Confirm for each route that authentication runs first and that unauthenticated requests are rejected before any allow list is evaluated.

Before rollout, decide how consumers map to access groups, for example one consumer per partner or application and a shared allow list per route. Then test denials as well as allows. Send requests with a valid credential for a consumer that is not on the list, confirm the rejection status and check the access logs for the consumer name. The plugin list in the APISIX plugin documentation describes the related security plugins, and the APISIX consumer documentation explains how consumer settings interact with route and plugin configuration. Confirm the exact behavior for your APISIX version in its release notes before you rely on it in production.

Choosing between consumer-restriction, acl and per-route allow lists

This table compares the three ways to limit which consumers can call a route in APISIX, covering what each matches on, where it attaches and how it depends on authentication. Read it before writing any allow list, since the choice shapes how much configuration you maintain as consumers and routes grow.

Decision pointconsumer-restriction pluginacl pluginPer-route allow list in your own config
What it matches onConsumer name by default, with options to match on other fields that the plugin documents for your versionConsumer group names assigned to each consumerWhatever identity your own config encodes, such as a consumer name list or a label you maintain
Where it attachesRoute, service or plugin config, with consumer-level and route-level precedence to confirmRoute, service or plugin config, with consumer-level and route-level precedence to confirmRoute definitions in your repository or Admin API payloads
Dependency on authenticationNeeds an authentication plugin earlier on the route so a consumer is identifiedNeeds an authentication plugin earlier on the route so a consumer group is knownNeeds authentication to produce an identity that the list can compare against
Maintenance when a consumer is addedUpdate the allow list on each affected route unless a shared attachment covers itAssign the consumer to an existing group, so routes need no changeEdit every route or generate the list from a source of truth
Maintenance when a route is addedCopy the allow list or attach a shared plugin configAttach the existing ACL plugin config to the new routeRepeat the list in the new route definition unless generated
Labels and metadataConfirm whether your version supports matching on consumer labelsGroups act as the label; confirm group behavior for your versionLabels can be kept in your inventory and used to build lists
Denial behavior and statusConfirm the default rejection code and message in your versionConfirm the default rejection code and message in your versionDepends on what your gateway config returns; test it explicitly
Best fitSmall, stable sets of named consumers on a few routesMany consumers sharing a few permission tiersRules generated from an authoritative source that you review before rollout

Design decisions that shape the allow lists

Most allow-list problems come from modeling choices made before any plugin is configured. The six decisions below connect consumer design, route policy and change control, and each one sets how much work the allow lists create later.

Consumer per application or per partner

A consumer in APISIX identifies one API caller by username, so the first choice is whether that caller is an internal application, a partner organization or a single integration inside a partner. Per-application consumers keep permissions tied to deployed software, while per-partner consumers match contracts and offboarding. Check whether a partner runs several integrations that need different routes, because a single partner consumer then grants them all the same access.

Consumer groups or named consumers

Named consumers receive routes one by one, which is precise but grows with every new client. Consumer groups let several consumers share a policy, such as a shared rate limit or a common plugin set, so an allow list can reference a group. Use groups for tiers like partner-standard or internal-batch, and keep a named consumer where a single client needs an exception. Mixing both without a naming rule makes it hard to tell which policy applies to a given caller.

Deny-by-default or allow-by-default

Under deny-by-default, a route is reachable only by consumers listed on it, so every new route starts closed and a missed entry produces a denial. Under allow-by-default, routes are open unless restricted, which is faster to build but leaves any route added without a review exposed. For regulated APIs, deny-by-default is the safer starting point, with exceptions documented for each route that opens wider. Confirm which default your gateway template applies before routes are copied.

Labels for tagging consumers

Consumer labels are key-value tags that can describe ownership, data class or contract reference. They help auditors and operators find every consumer that touches a sensitive route, and they can drive reviews that the allow list alone cannot. Labels only help if the team agrees on a fixed vocabulary, such as owner, environment and data-class keys, because free-form values drift quickly. Confirm how your APISIX version exposes labels to the plugins and tooling you plan to use.

How often allow lists change

Allow lists change when partners onboard, when a new route is published or when a consumer is retired, and the frequency sets how automated the process must be. Frequent changes favor generating allow lists from consumer definitions in version-controlled configuration, while infrequent changes can use reviewed manual edits through the Admin API. Estimate the monthly change volume with the team that owns partner onboarding before choosing the tooling, and plan a periodic review that removes consumers no longer in use.

Who approves allow-list changes

An allow-list change grants a caller access to a route, so approval belongs to the owner of that API or the data behind it, not only to the gateway team that applies the change. Separating the requester, the approver and the person who applies the change gives auditors a clear trail for each grant. Write the approval path into the change process before rollout, and confirm that every change is traceable to a ticket and a named approver.

Configuring consumer restrictions step by step

This sequence takes a test route from open access to consumer-level control, so that only the callers you name can reach it. Each step ends with a check you can run before the restriction touches production traffic.

  1. Confirm the authentication plugin identifies consumers

    Before any restriction is added, confirm that the route authenticates callers and maps each request to a consumer. In APISIX, a consumer is identified by its username, and authentication plugins such as key-auth, jwt-auth, hmac-auth or ldap-auth are what establish that identity. On a test route with a single authentication plugin attached, send one request with a valid credential and confirm it succeeds. Then send one with no credential and confirm it is rejected. You know this step is done when the valid request reaches the upstream and the invalid one fails at the gateway, not at the upstream.

  2. Create consumers and their credentials

    Create one consumer per application, partner or service that should be distinguishable in logs and policy. Use the Admin API to create each consumer by username, then attach a credential that matches the authentication plugin you confirmed in the previous step. Keep consumer names stable, because the allow list will refer to them. Confirm the Admin API address, port and access controls for your deployment mode in the deployment documentation before you call it, since traditional and standalone modes configure this differently. You know this step is done when a GET request to each consumer returns the expected username and credential reference.

  3. Attach the restriction plugin to a test route

    Choose consumer-restriction or acl based on how you want to express the rules. Attach the chosen plugin to a dedicated test route, not a production route, and keep the authentication plugin enabled on the same route so that the restriction has a consumer to evaluate. Use a route that has no other consumer-facing policy, so that any denial you see can be traced to this change. Confirm the plugin's configuration keys for your APISIX version in its documentation. You know this step is done when the Admin API returns the route with both plugins listed in its configuration.

  4. Define the allow list on the route

    Add the permitted consumer names to the restriction plugin configuration. Start with a short list that includes only the consumers that should reach this route. Leave out any consumer that does not need access, rather than adding a broad group and narrowing it later. If you use consumer labels or groups, confirm in the plugin documentation whether your version supports matching on them before relying on that approach. Record the list in version control with the route definition so the change can be reviewed. You know this step is done when the stored route configuration shows exactly the consumers you intended to allow.

  5. Test a permitted consumer

    Send a request using a credential that belongs to a consumer on the allow list. The request should pass authentication and restriction, and reach the upstream. Check the response status and confirm in the access log that the consumer name is recorded against the request. If the request is denied, review the allow list spelling against the consumer username before changing anything else. You know this step is done when a permitted credential returns the upstream response with a successful status code.

  6. Test a non-permitted consumer and a missing credential

    Send a request with a valid credential for a consumer that is not on the allow list, then send one with no credential at all. The first should return a denial from the restriction plugin, and the second should fail at authentication. Confirm that neither request reaches the upstream by checking the upstream logs for the test path. Record the status codes returned for each case, since these are the denials your monitoring and client teams will see. You know this step is done when both requests are refused at the gateway and the upstream log shows no entry for them.

  7. Repeat the tests before rollout to production routes

    Repeat the permitted and denied tests against the same route after any change to consumers, credentials or the allow list. Run the same set on each environment that will carry the route, and confirm your environment's ports and Admin API settings before each run. Only then apply the same restriction to the production route, using the same configuration you tested. Keep the previous route definition available so you can restore it if a legitimate client is denied. You know this step is done when the full test set passes on the staging route and the production change matches the tested configuration.

Testing denials before rollout

Treat every consumer restriction as untested until a denial has been observed for the right consumer on the right route. Build a test matrix that pairs each consumer with each route it should reach and each route it must not reach. For every pair, include a positive case with valid credentials and a negative case with the wrong consumer, a consumer outside the allowed group, and a request with no credentials at all. Add cases for revoked consumers, meaning a consumer whose credential has been disabled or deleted, and for consumers moved between groups, because a stale group membership is one of the more common ways an allow list drifts from the intended design. Confirm how your chosen authentication plugin responds to a missing credential so the expected status code in each case matches what the gateway actually returns.

Run the matrix in a non-production APISIX instance that mirrors production: the same plugin versions, the same route and consumer objects, the same plugin precedence, and the same identity source feeding consumer data. A gap between the test gateway and production is the usual reason a restriction passes review and then blocks or admits the wrong traffic. Keep the test definitions in version control so each configuration change reruns the full matrix. Confirm with your team which tooling will execute the cases, since the supplied material does not establish a specific testing framework for this gateway. Check the gateway's error log and access log during the runs so you can confirm that each denial was recorded with the consumer and route you expected.

Roll out in stages. First, add the deny rules in a mode where denied requests are logged but existing access continues, so you can compare the requests that would be blocked against the traffic clients actually send. Review those entries with the application owners and remove any consumer that appears because of an undocumented dependency before enforcement begins. Then enforce on one low-risk route, watch denial volume and client error rates, and extend to remaining routes only after the first one behaves as the matrix predicts. Agree in advance who can reverse a restriction and how quickly, so a blocked partner integration does not stay down while the team investigates.

Security and operational risks to manage

Consumer restriction only protects routes that the allow list actually covers, and the list is only as trustworthy as the consumer records and the people who can edit them. The cards below cover the configuration, identity and operational failure modes that most often undo an otherwise correct design.

Allow-by-default configuration

A route with an authentication plugin but no consumer-restriction or acl rule accepts any consumer that passes authentication. Review each route as a unit: confirm which plugins run on it, which consumers or groups are listed, and whether the list is empty by accident. Test with a consumer that is valid but not on the list, and expect a denial.

Offboarded consumers still active

Removing a consumer from an allow list does not remove its credentials. A consumer record that still holds a valid key, secret or certificate mapping can keep authenticating on any route that lists it through a group or label. Define an offboarding step that disables or deletes the consumer and its credentials, and check that the step runs in the Admin API, not only in your ticketing system.

Shared credentials across consumers

If two partners or applications use the same key or secret, the gateway sees one consumer and cannot separate them. An allow list then grants or revokes both at once, and logs cannot show which caller acted. Issue one consumer and one credential per application or partner, and confirm in the consumer documentation how identity is established for each authentication plugin you use.

Restrictions attached to the wrong object

Plugin precedence in APISIX runs Consumer, then Route, then Plugin Config, then Service. A restriction attached to one route does not cover a second route that reaches the same upstream, and a new route created by a developer may have none. Inventory which object carries each restriction, and review new routes against that inventory before they receive traffic.

Admin API access to allow lists

Anyone who can call the Admin API can edit a consumer-restriction or acl rule, and the Admin API listens on a separate port from client traffic in traditional mode. Limit Admin API access to named operators and automation accounts, keep it off public networks, and treat changes to allow lists as privileged actions. Confirm the access controls against the hardening guidance for your APISIX version.

Change control and monitoring

Allow lists change for ordinary reasons, such as a new partner or a retired integration, and each change can open or close access. Require a reviewed change record for every edit, keep an audit trail of who changed what, and watch denial rates per route and consumer. A sudden rise in denials can signal a broken client or a probe, and a sudden fall can signal a rule that was removed.

Questions teams ask before restricting API access in APISIX

How much effort does a per-consumer restriction take for a set of routes and partners?

Effort scales with the number of routes, the number of consumers and how many distinct access rules you need. A small set of routes with one shared rule is a short configuration task. Mapping many partners to different route sets, with exceptions and review steps, is a larger piece of work that also includes writing the access matrix and testing each denial. Ask any partner for a written scope that lists the routes, consumers and rules in scope, because that list drives the estimate more than the plugin configuration itself.

What drives the cost of consumer restriction up or down?

Four factors matter most:

  • Consumer count: each partner or application needs its own consumer, credential and group mapping.
  • Route count: every route needs an explicit decision about who may call it.
  • Change frequency: a stable allow list costs far less to maintain than one that changes every sprint.
  • Testing depth: negative tests for each denied consumer and route take time, but they are the step that catches mistakes before production.

One-time work covers design, configuration and testing. Recurring work covers onboarding new consumers, reviewing access and removing retired clients.

Can an internal team restrict API access in APISIX without a partner?

Yes, if the team already runs APISIX, understands its consumer model and has an owner for each route. The consumer-restriction and acl plugins are configured through the Admin API or declarative configuration, so the work is standard gateway administration. A partner adds value when the access model is complex, when many routes must be reviewed at once, or when the team lacks time to write negative tests. Confirm your team's APISIX experience and change process before deciding.

What do you need to provide before restriction work starts?

Prepare three inputs before work begins:

  • Route inventory: every route, its upstream service and its current authentication plugin.
  • Consumer list: each application, partner or service account, with its owner and the routes it needs.
  • Owners and approval rules: who signs off on access changes, and how emergency removals are approved.

Without these, the access matrix is guesswork. Agree on the format in writing so that the scope, deliverables and timeline are fixed before implementation starts.

How long should testing before rollout run?

The length depends on your change process, the number of routes and how many consumers are affected. Testing should cover allowed calls, denied calls for every consumer that should not reach a route, and behavior when a credential is missing or invalid. Run these tests in a non-production environment that matches your gateway configuration, then in a staged rollout if your change process allows it. Confirm the required testing window and approval steps with your change board before setting a date.

Do consumer restrictions replace identity provider authorization?

No. Consumer restrictions in APISIX decide which identified API clients may call a route at the gateway. They do not replace the authorization decisions your identity provider or application makes about individual end users, such as roles, scopes or record-level rules. Many designs use both: the gateway limits which applications reach an API, and the service or identity provider checks what each user may do. Confirm which layer owns each decision before you write the access matrix.

Which APISIX plugin should I use for consumer restriction?

Use consumer-restriction when access depends on the consumer name or another consumer attribute, and use acl when you assign consumers to named groups that several routes share. Both work after an authentication plugin such as key-auth or jwt-auth has identified the consumer. Check the plugin documentation for the version you run, because option names and behavior can change between releases.

How DeployOpen scopes and delivers consumer restrictions for APISIX

DeployOpen plans, builds and hands over consumer restrictions for APISIX inside your own infrastructure, starting from a written scope that lists the routes, consumers and denial cases involved. We pair each restriction with the authentication already in place, then prove the denials work before any traffic moves to the gateway.

How we scope

  • Inventory every route that needs a consumer allow list, and record which consumers may call each one.
  • Confirm which authentication plugin identifies each consumer before choosing between consumer-restriction and acl.
  • Agree in writing which denial responses, status codes and logs your teams and partners will see.

How we build

  • Configure per-route allow lists and consumer labels in a version-controlled repository, not by hand in the dashboard.
  • Set plugin precedence so consumer-level and route-level rules behave the way the scope describes.
  • Run a denial test matrix covering every consumer and route pair, including unauthenticated and expired-credential calls.

How we hand over

  • Deliver the configuration, the test matrix with recorded results, and a runbook for adding or removing a consumer.
  • Document the rollout order, the rollback steps and the monitoring checks to run after each change.
  • Walk your platform and security teams through the access model so they can review changes independently.

How we support

  • Ongoing support, upgrades and continuous testing are available as a retainer after handover.
  • Re-run the denial matrix whenever APISIX, its plugins or your consumer list changes.
  • Engagements are fixed-scope, with scope, deliverables and timelines agreed in writing before work starts.

Talk to our team.

Tell us what you're working on, whether it's a deployment, an audit, a security test or a cyber range. You'll speak with an engineer who can help you scope it.

  • 30-minute call: free, with no obligation.
  • NDA on request: we can sign before you share details.
  • Clear next steps: a scope and plan after the call.