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.
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.
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")'
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.
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.
# 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.