Entitlement Enforcement

Enterprise only
Related Documentation
Made by
Kong Inc.
Incompatible with
on-prem
Supported Gateway Topologies
Supported Konnect Deployments
hybrid cloud-gateways serverless
Compatible Protocols
grpc grpcs http https
Priority
915
Minimum Version
Kong Gateway - 3.16

Metering & Billing requires a separate purchase. Contact Sales for pricing and availability.

The Entitlement Enforcement plugin blocks API requests based on the customer entitlements defined in Metering & Billing. It works alongside the Metering & Billing plugin: Entitlement Enforcement checks the customer’s current usage against their entitlement and decides whether to allow the request, before it reaches your upstream service. Metering & Billing then reports the request as new usage.

The plugin blocks a request when a customer:

  • Has reached the usage limit for a metered feature.
  • Doesn’t have access to a boolean feature, for example because a subscription expired or a feature isn’t included in their plan.

Requests from customers that are within their entitlements are allowed through.

How it works

For each request, the Entitlement Enforcement plugin:

  1. Resolves the customer’s subject key from the configured source: a Consumer, a Dev Portal application, or a request header or query parameter. This is the same subject the Metering & Billing plugin uses to attribute usage, so both plugins agree on who’s being billed.
  2. Looks up the cached enforcement state for that subject in a local, per-worker cache.
  3. If the feature is available and the customer’s usage is within their entitlement, allows the request.
  4. If the feature is unavailable or the usage limit is reached, blocks the request with the configured HTTP status and message.

The following diagram shows the request’s path through the plugin:

 
sequenceDiagram
    participant Client
    participant Enforcement as Entitlement Enforcement
    participant Cache as Local cache
    participant Service as Upstream service
    participant Metering as Metering & Billing

    Client->>Enforcement: Request
    Enforcement->>Cache: Check cached state
    alt If allowed
        Cache-->>Enforcement: Allowed
        Enforcement->>Service: Forward request
        Service-->>Metering: Report usage
    else If blocked
        Cache-->>Enforcement: Blocked
        Enforcement-->>Client: HTTP error
    end
    note over Cache: Cache refreshed from Redis every sync_rate seconds.
Redis is refreshed from the Entitlement Access API every refresh_interval seconds.

The request only ever waits on the local cache. Redis and the Entitlement Access API are updated on their own schedules, never as part of handling a request.

Each Entitlement Enforcement plugin instance attaches to a single feature, set with config.feature.key. To enforce more than one feature, add a plugin instance per feature on the Routes that serve it.

The plugin never calls the Metering & Billing Entitlement Access API directly from the request path. Instead, a background timer polls the endpoint on config.refresh_interval and writes the result to Redis, and a second timer syncs Redis into each worker’s local cache on config.sync_rate. This two-tier cache keeps the request path fast and avoids calling the Entitlement Access API on every request.

Because enforcement state is cached and refreshed on an interval, it’s eventually consistent, not real time. A customer’s usage has to be reported and aggregated in Metering & Billing, then polled by the plugin, before enforcement reflects it. See Cold start and fail policy for what happens the first time the plugin sees a customer, and when it can’t retrieve enforcement state at all.

Excluding blocked requests from usage

By default, the Metering & Billing plugin meters every request that reaches its Route, including requests that Entitlement Enforcement blocks. The two plugins act independently, so a blocked request still counts as usage unless you configure one of the plugins to exclude it.

To stop blocked requests from counting toward a customer’s usage, use one of the following:

  • Set config.allow_status_codes on the Metering & Billing plugin to only log usage events for successful response codes, for example 200-299.
  • Set meter.filters on the metered feature to filter its meter’s dimensions, for example on an HTTP status dimension, so only events for successful requests count toward the entitlement.

Enforcement decisions and response codes

When the plugin blocks a request, it returns an HTTP status and message based on the denial reason. You can override the status and message for each reason with config.response_codes.

Reason code

Default HTTP status

Default message

When it happens

USAGE_LIMIT_REACHED 429 Customer has reached usage limit for feature. The customer’s usage of a metered feature has reached the limit defined in their plan.
FEATURE_UNAVAILABLE 403 Feature is not available for the customer. The customer doesn’t have access to a boolean feature, for example because their subscription ended or the feature isn’t in their plan.
FEATURE_NOT_FOUND 403 Feature not found. The configured feature.key doesn’t match a feature returned for the customer.
CUSTOMER_NOT_FOUND 403 Customer is not found by subject. The plugin can’t resolve a customer for the request’s subject key. This also covers unknown subjects when deny_unknown_customers is true.
NO_CREDIT_AVAILABLE 402 Customer has no credit available. Reserved, not yet functional. This reason code exists in the schema for credit balance enforcement, a capability that isn’t implemented yet. See Limitations.

The response body for a blocked request contains the message and reason code, for example:

{
  "message": "Customer has reached usage limit for feature.",
  "reason": "USAGE_LIMIT_REACHED"
}

Configuring the customer

Set config.customer.look_up_value_in to tell the plugin where to find the customer identifier in the request:

Value

Description

consumer Use the authenticated Consumer’s ID as the subject, sent as consumer:<consumer-id>. This is the default.
application Use the Dev Portal application ID as the subject, sent as app:<application-id>.
header Use the value of the request header named in config.customer.field.
query Use the value of the query parameter named in config.customer.field.

Use the same subject source for both the Metering & Billing plugin and the Entitlement Enforcement plugin so usage and enforcement resolve to the same customer.

Cold start and fail policy

The plugin can’t enforce entitlements for a customer it hasn’t cached yet. The first request from a new subject is treated as unknown: the plugin records the subject and returns CUSTOMER_NOT_FOUND (if config.deny_unknown_customers is true), then fetches that customer’s entitlements on the next poll of the Entitlement Access API. Retry the request after config.refresh_interval seconds to get an enforcement decision based on the customer’s actual entitlements.

Set config.fail_policy to control what happens when the plugin can’t retrieve enforcement state at all, for example if Redis is unreachable:

  • allow (default): let the request through.
  • block: block the request.

Relationship to rate limiting

Entitlement Enforcement doesn’t replace rate limiting. Rate limiting plugins like Rate Limiting Advanced protect infrastructure and reset on a fixed schedule, such as requests per second or tokens per minute. Entitlement Enforcement protects business logic, such as plan limits and feature access, and resets on billing events.

You can use both together: for example, a customer might have a monthly token allowance enforced by this plugin, and a per-minute rate limit to prevent a single burst of traffic from consuming that allowance too quickly.

Limitations

Credit balance enforcement isn’t implemented yet. The following config fields exist in the plugin’s schema but currently have no effect:

The plugin currently enforces usage limits and feature access only. See the known issues for details.

Help us make these docs great!

Kong Developer docs are open source. If you find these useful and want to make them better, contribute today!