Sign in →
1 min read

Kong Gateway Integration

Enable the Aforo metering plugin on your existing Kong cluster. Zero application code changes required.

Updated 2026-07-29Suggest edits

Task Overview#

JIRA-READY TASK
Enable the Aforo metering plugin on your existing Kong cluster. Verify handshake with SRE team before promoting to production.
Estimated time: 15 minutes. Target: Platform Engineer + SRE Verification.
kong-deployment-architecture.flowLIVE
INGRESS
HTTP In
client request
TLS termination at Kong gateway. Headers parsed and route matched.
0ms
ACCESS
Entitlement
access phase
Local Redis lookup for workspace entitlement + L1-L3 margin check.
<2ms
PROXY
Backend
upstream call
Request forwarded to your origin service. Response streamed back.
passthrough
LOG
Metering
log_by phase
Async event capture after response sent. Zero latency added to client.
0ms added
BUFFER
Batch Flush
every 5s
50 events per batch (flush_count), or every flush_interval_ms.
5s window
EGRESS
Aforo Ingest
ingest.aforo.ai
HTTPS POST with retry. Acknowledged by ingest pipeline.
<50ms
kong → aforo metering pipeline · zero client-perceived latency// p95 < 5ms

Prerequisites#

REQUIRED
Kong Gateway
OSS 3.x+ or Enterprise 3.x+
REQUIRED
Admin API access
HTTP access to Kong Admin API (default: localhost:8001)
REQUIRED
Aforo API Key
sk_live_* key from Workspace Admin → API Keys
OPTIONAL
Redis (optional)
For local edge cache. Falls back to in-memory LRU if unavailable.

Step 1: Get the Plugin#

The Kong plugin lives in the Aforo SDK distribution repo at aforo-gateway-plugins/kong/. It is not yet on the public LuaRocks registry, so build and install it from source. Clone the repo, then make the plugin from the rockspec in that folder:

terminal
# Clone the SDK distribution repo and enter the Kong plugin folder
git clone https://github.com/aforoai/SDKs.git
cd SDKs/aforo-gateway-plugins/kong

# Install the runtime dependency used by the log-phase flush
luarocks install lua-resty-http

# Build + install the plugin from the rockspec in this folder
# (run 'ls *.rockspec' to confirm the version on your checkout)
luarocks make kong-plugin-aforo-metering-2.0.2-1.rockspec

# Verify the plugin is loadable
kong version -vv 2>&1 | grep aforo

Then load it in kong.conf and reserve the buffer the log phase writes to — plugins = bundled,aforo-metering and nginx_http_lua_shared_dict = aforo_buffer 10m — then run kong reload. The shared-dict line is mandatory; without it the log phase drops every event.

Step 2: Configure#

Add the plugin to your kong.yml declarative config or apply via Admin API:

Option A: Declarative (kong.yml) — Production Ready

kong.yml
plugins:
  - name: aforo-metering
    config:
      # ── Core (required) ──────────────────────
      aforo_endpoint: "https://ingest.aforo.ai/v1/ingest/batch"
      api_key: "{vault://env/AFORO_API_KEY}"    # env var injection
      tenant_id: "your-workspace-id"            # static workspace id (sent as X-Tenant-Id)

      # ── What to meter ────────────────────────
      metric_name_pattern: "{method} {path}"    # vars: {method} {path} {service} {route} {consumer}
      quantity_source: "1"                       # "1" (count), "response_size" (bytes), or a number
      customer_id_source: "consumer"             # Kong consumer identity (JWT claim wins when JWT is on)

      # ── Batching ─────────────────────────────
      flush_count: 50                            # events per flush
      flush_interval_ms: 5000                    # or flush every 5s

      # ── MCP (optional) ───────────────────────
      mcp_enabled: false
      mcp_product_id: ""                         # required when mcp_enabled: true

      # ── Margin Guard (optional) ──────────────
      margin_guard_enabled: false
      margin_guard_url: ""
      margin_guard_cache_ttl: 30

      # ── Skip rules (optional) ────────────────
      exclude_paths: ["/health", "/metrics"]
      exclude_status_codes: [401, 403]
INFO
Only the three Core fields are required. Everything below has sensible defaults — flush_count 50, flush_interval_ms 5000, metric_name_pattern {method} {path}. Customer identity comes only from the Kong consumer (or a validated JWT claim), never a client-settable header.

Option B: Admin API

terminal
curl -X POST http://localhost:8001/plugins \
  -H "Content-Type: application/json" \
  -d '{
    "name": "aforo-metering",
    "config": {
      "aforo_endpoint": "https://ingest.aforo.ai/v1/ingest/batch",
      "api_key": "sk_live_your_key_here",
      "tenant_id": "your-workspace-id",
      "flush_count": 50,
      "flush_interval_ms": 5000
    }
  }'
INFO
The Admin API method applies the plugin globally (all routes). To scope to a specific service or route, add service.id or route.id to the request.

Step 3: Deploy#

After configuration, reload Kong to activate the plugin:

terminal
# For traditional mode (database-backed)
kong reload

# For DB-less mode (declarative)
kong reload -c /etc/kong/kong.conf

# Verify the plugin is active
curl -s http://localhost:8001/plugins | jq '.data[] | select(.name == "aforo-metering")'

Performance: Zero Latency Impact#

The Aforo Kong plugin is designed for zero impact on your API response times:

<5ms
Entitlement Check
Local Redis lookup. No cross-network call.
0ms added
Usage Metering
Fires in Lua log_by phase — after response is sent.
Every 5s
Batch Flush
50 events per batch (flush_count). Async HTTP in the log phase.
30s TTL
Cache Refresh
Background sync. Stale cache serves until refresh.
<5ms
Kong Edge Decision
Local Redis lookup in access phase. Zero cross-network call.
MARGIN GUARD/ Kong
The plugin operates in Kong's log phase for metering and access phase for entitlement + margin checks. L1-L3 enforcement runs before the request reaches your upstream — unprofitable traffic is blocked at the gateway.

Fallback Behavior#

If the Aforo ingestion endpoint is temporarily unreachable, the plugin guarantees zero data loss:

RESILIENCE CHAIN
1. Normal → Events buffered in the aforo_buffer shared dict and flushed every 5s to ingest.aforo.ai
2. Ingest unreachable → The batch is retried with exponential backoff (1s, 2s, 4s)
3. Retries exhausted → The batch is dropped and counted (drop metric) rather than blocking traffic
4. Ingest recovered → Buffering + flush resume on the next request
INFO
Metering runs in Kong's log phase, after the response is sent — so a metering failure never blocks or delays an API request. Entitlement/margin checks in the access phase fail open (traffic continues) if Aforo can't be reached.

Verification#

Verify the handshake by checking Kong logs for a successful connection:

terminal
# Check Kong error log for Aforo handshake
tail -f /usr/local/kong/logs/error.log | grep aforo

# Expected output:
# [aforo-metering] Connected to ingest.aforo.ai (200 OK)
# [aforo-metering] Entitlement cache warmed: 47 tenants loaded
# [aforo-metering] Batch flush: 100 events sent (compressed: 2.4KB)

PaperPlaneTilt a Test Event

terminal
# Make an API call through Kong
curl -X GET http://localhost:8000/your-api/endpoint \
  -H "X-Tenant-Id: test_tenant_123" \
  -H "Authorization: Bearer sk_live_your_customer_key"

# Then verify the event arrived in Aforo
curl -s https://api.aforo.ai/v1/events?tenant_id=test_tenant_123&limit=1 \
  -H "Authorization: Bearer sk_live_your_admin_key" | jq .
PRO TIP
If events are not appearing, check the Kong error log for [aforo-metering] ERROR entries. Common issues: invalid API key (401), network timeout to ingest.aforo.ai, or missing X-Tenant-Id header on the request.