Framework Files vs User Files
The framework uses a layered file system that separates auto-generated configuration from your customizations. This pattern keeps your changes safe during upgrades while allowing the framework to evolve its defaults.
The merge pattern
Many configuration areas follow a three-file pattern:
When you run a generate command, the framework merges the two input files to produce the final configuration.
Example: Secrets
Example: Kong
Why this pattern exists
The merge pattern solves a common framework dilemma: how do you provide sensible defaults while allowing customization?
Without this pattern, you would face difficult choices:
- Copy and modify: Fork the entire config, but lose framework updates
- Manual patching: Apply framework changes by hand after each upgrade
- Configuration flags: Limited to what the framework anticipated
With this pattern, you get the best of both worlds:
- Framework generates baseline configuration automatically
- Your customizations layer on top, preserved across regenerations
- Upgrades can improve framework defaults without touching your code
- Clear separation makes it obvious what you changed
How merging works
The merge strategy depends on the data type:
Objects (deep merge)
User values override framework values at each key:
Arrays (concatenation)
When both files contain arrays for the same key, entries from both are combined. For example, Kong services from the framework file and custom services from the user file end up in the same list:
Not every key follows simple concatenation. Kong's merge is structured per key — see Kong Customization for details.
When framework files regenerate
Framework files (*.tsdevstack.*) regenerate in these situations:
Your user files are never modified by the framework.
Note on secrets preservation: When .secrets.tsdevstack.json regenerates, critical values are automatically preserved: JWT keys, service API keys, database credentials, and KONG_TRUST_TOKEN. The file is rewritten, but these values are read first and carried forward. Only delete .secrets.tsdevstack.json if you need completely fresh credentials.
Safe customization practices
Do: Edit user files
Do not: Edit framework files
The gateway image is generated too. Custom Kong plugins go in kong-plugins/ at the project root, which is yours and never touched by the framework. See Kong Plugins.
Do not: Edit merged output
What to commit
Configuration files you CAN commit:
kong.user.yml- your Kong customizations (no secrets)kong.tsdevstack.yml- framework Kong routes (no secrets)docker-compose.user.yml- your Docker additionskong-plugins/- your custom Kong plugins (CI builds the cloud gateway image from it)
Files you should NOT commit:
kong.yml- merged output with resolved placeholder valuesinfrastructure/kong/kong-plugins/andinfrastructure/kong/declarative/- generated build context (gitignored in new projects).secrets.*.json- all secret files (contains credentials).env- generated environment variables
Use .secrets.user.example.json (committed) to document what secrets your project needs:
Developers copy this to .secrets.user.json and fill in actual values.
When merging is not enough
Sometimes the framework's automatic generation does not fit your needs. For these cases, escape hatches provide full control:
See Escape Hatches for details on when and how to use these overrides.
Troubleshooting
My customizations disappeared
You likely edited a framework file or the merged output. Check which file you modified:
- If it ends in
.tsdevstack., it is framework-managed - If it has no suffix before the extension, it is probably the merged output
- Only
*.user.*files preserve your changes
Framework file has unexpected content
The framework regenerates from your source code (OpenAPI specs, decorators, service definitions). Check whether your source changed.
Merge conflict between framework and user values
User values always win. If you see unexpected behavior, check whether your user file overrides something important. Remove the override to restore framework defaults.