Kong Customization
The framework generates Kong Gateway configuration automatically, but you can customize it for your specific needs. This guide explains the configuration file system and how to add your own settings.
Configuration files
Kong configuration uses a layered file system:
The framework merges kong.tsdevstack.yml and kong.user.yml to create the final kong.yml. The merge is structured per key:
- Services — combined from both files (framework routes first, then your custom services)
- Consumers: taken from
kong.user.ymlas written. The framework generates none, and no generated route authenticates with them (see Partner API keys) - Plugins: framework global plugins first (today one:
tsdevstack-strip-identity), then yours fromkong.user.yml. Service-level plugins (oidc on JWT routes; the API key check, the per-IP ceiling andtsdevstack-api-prefixon partner routes) are attached inside the individual service definitions. Kong allows one global instance per plugin name, so akong.user.ymlthat declares a framework global plugin fails generation with a hint
Customizing with kong.user.yml
Edit kong.user.yml to add global plugins or custom services. This file is created once and preserved across regenerations.
The trust header (request-transformer)
The generated kong.user.yml starts with a request-transformer that proves to your backends that a request came through Kong:
It removes any client-sent X-Kong-Trust and adds the real token. Keep it: backends reject identity headers on requests without a valid trust token (see Protected Routes).
Only X-Kong-Request-Id and X-Kong-Trust belong in its remove list. Client-sent identity headers (X-Userinfo, X-Consumer-*, X-Credential-Identifier and so on) are removed by the framework plugin tsdevstack-strip-identity, which runs before authentication. The request-transformer runs after authentication, so removing identity headers there deletes the values Kong itself just set; for example removing X-Api-Key-Consumer leaves @Partner() without a consumer name.
Files created by earlier versions list X-Consumer-Id, X-Consumer-Username and sometimes X-JWT-Claim-* headers in that remove list. Delete those entries and keep only X-Kong-Request-Id and X-Kong-Trust. generate-kong and infra:generate-kong print a warning while identity headers are still listed.
Global plugins
Add plugins that apply to all routes:
The global rate limiter and API keys
The global rate-limiting plugin limits every caller per IP. On partner routes (/api/...) it works differently: its minute, hour, day and month values become the default limits of every API key, counted per key, and a key's own limits replace them. On those routes a per-IP ceiling (framework.apiKeys.ipLimitPerMinute in .tsdevstack/config.json, 600 by default) takes its place. Details in API Keys.
Partner API keys
Partner keys are not configured here. Admins create, limit, rotate and revoke them at runtime through the auth-service admin API, and the gateway checks them against Redis. See API Keys.
Earlier versions defined partners as consumers with keyauth_credentials in this file. Those keys no longer work on partner routes; generate-kong and infra:generate-kong warn while such consumers are still listed. Move the partners to API keys (Migrating from static partner keys), then delete the consumers and their key secrets.
Custom services
Add services not managed by the framework:
CORS configuration
Configure allowed origins in your secrets file:
The framework automatically converts this comma-separated string to an array in the final configuration.
Escape hatch with kong.custom.yml
For complete control, create kong.custom.yml. When this file exists, the framework skips automatic route generation and only resolves secret placeholders.
In custom mode you own everything the framework would otherwise generate, including the security pieces:
tsdevstack-strip-identityas a global plugin. Without it, clients can send forged identity headers (X-Userinfo,X-Consumer-*) to your backends.generate-kongwarns when it is missing.- The trust header
request-transformerfrom above, or backends reject identity headers. tsdevstack-api-prefixon partner services (config.prefix: /api) if you publish partner routes at/api/...and your services serve the path without/api.tsdevstack-api-keyon partner services, with the Redis connection anddefault_limits, plus a service-scopedrate-limitingcounted per IP as the ceiling. Without the key plugin, partner routes check no key at all. Copy both from a generatedkong.tsdevstack.yml.
The same request-transformer check applies: identity headers in its remove list produce a warning. See Kong Plugins for what the framework plugins do.
To return to automatic generation, rename or delete the file:
Custom Lua plugins
Your own Lua plugins go in the kong-plugins/ folder at the project root and are baked into the gateway image, locally and in the cloud. See Kong Plugins.
Applying changes
After editing configuration files:
This regenerates Kong configuration and restarts the gateway.
Secret placeholders
Use ${SECRET_NAME} syntax in configuration files. The framework resolves these from your secrets files during generation:
Common customizations
Increase rate limits for a partner
Raise the limits of the partner's API key through the admin API (PATCH /auth/v1/admin/api-keys/:id). It applies on the next request, with no gateway redeploy. See API Keys.
Configure upload size limits
The default maximum request body size is 10MB, configurable via infrastructure.json:
This sets Kong's nginx client_max_body_size. Values use nginx-style format: "10m", "50m", "1g", "0" for unlimited. Requests exceeding this limit receive 413 Content Too Large.
For files larger than the configured limit, use presigned URL uploads which bypass Kong entirely. See Object Storage — File Uploads.
Add request size limits (per-route via plugin)
For more granular control, use the Kong request-size-limiting plugin in kong.user.yml:
Enable response caching
Troubleshooting
Changes not taking effect
- Run
npx tsdevstack syncto regenerate and restart
API key rejected
- Check the
errorcode in the response body against the table in API Keys - Keys from
consumersinkong.user.ymlno longer work; create the key through the admin API
Customizations lost after sync
- Edit
kong.user.yml, notkong.tsdevstack.yml - The framework file is regenerated; the user file is preserved