KrakenJS Configuration: Environment‑Specific JSON, Secrets, and Engineering Trade‑offs
KrakenJS’s JSON‑based config system lets you merge base and environment files, inject secrets via ${ENV_VAR}, and make settings available through app.kraken. Learn how to set up, verify, and avoid common pitfalls in a practical example.
06 Aug 2026, 04:59 UTC

Why KrakenJS Configuration Matters
When a Node.js service grows beyond a handful of modules, a single source of truth for settings becomes essential. KrakenJS, a lightweight framework built on Express, offers a built‑in configuration loader that merges a base config.json with environment‑specific files such as config/development.json or config/production.json. The merged object is then injected into the Express app instance via app.kraken, allowing controllers to retrieve values with req.app.kraken.get('key') without resorting to globals.
Concrete Example: Setting Up a Multi‑Environment App
# Directory layout
project/
├─ config/
│ ├─ config.json
│ ├─ development.json
│ └─ production.json
├─ app.js
└─ package.json
1. Base configuration – config/config.json:
{
"port": 3000,
"db": {
"host": "localhost",
"port": 5432
},
"logging": {
"level": "info"
},
"apiKey": "${API_KEY}"
}
2. Environment override – config/production.json:
{
"port": 8080,
"db": {
"host": "prod-db.example.com"
},
"logging": {
"level": "warn"
}
}
3. App bootstrap – app.js:
require('dotenv').config(); // Load .env into process.env
const express = require('express');
const kraken = require('kraken-js');
const app = express();
kraken(app, {
configPath: __dirname + '/config',
env: process.env.NODE_ENV || 'development'
});
app.get('/', (req, res) => {
const port = req.app.kraken.get('port');
res.send(`Running on port ${port}`);
});
app.listen(req.app.kraken.get('port'), () => {
console.log(`Server listening on ${req.app.kraken.get('port')}`);
});
4. Run the app:
# Development
NODE_ENV=development API_KEY=dev123 node app.js
# Production
NODE_ENV=production API_KEY=prodSecret node app.js
During startup, KrakenJS will merge the base and environment files, perform top‑level string substitution for ${API_KEY}, and expose the final configuration via app.kraken. A quick sanity check is to log the merged config:
console.log(app.kraken.getConfig());
This confirms that db.host is prod-db.example.com and logging.level is warn in production, while the secret is correctly injected.
Engineering Decision: Storing Secrets Outside Version Control
The ${ENV_VAR} syntax is convenient, but only works on top‑level strings. For more complex secret structures, consider:
- Use separate
.envfiles per environment and load them withdotenv. - Create a custom loader that pulls from a secrets store (Consul, AWS Parameter Store) and merges the result into the config tree.
Example of a custom loader:
module.exports = async function customLoader() {
const secrets = await fetchSecretsFromAWS();
return { secretKey: secrets.apiKey };
}
Then register it in KrakenJS:
kraken(app, { loaders: [customLoader] });
Trade‑offs and Limitations
- Maintenance Mode: KrakenJS 2.x has not seen active development since 2017. Newer Node.js releases may introduce incompatibilities.
- Deep Merge Pitfalls: Nested objects are merged recursively. An environment override that mistakenly includes a full object can unintentionally overwrite shared properties. Always inspect
app.kraken.getConfig()during development. - Limited Validation: The loader only checks for the presence of required keys. For type checks, ranges, or format validation, integrate a schema library such as Joi or Ajv.
- Coupling via
app.kraken: Accessing the entire config from anywhere couples modules to the global state. Prefer passing only the needed slice to functions or controllers.
Actionable Checklist
- Place a
config/config.jsonwith shared defaults. - Add environment overrides (e.g.,
config/production.json) for secrets and feature flags. - Use environment variables for secrets and verify substitution with
console.log(app.kraken.get('apiKey')). - Implement a custom loader if you need secrets from external services.
- Integrate a schema validator to enforce types and ranges.
- Regularly review the merged config during development to catch accidental overrides.
By following these steps, you maintain a clean, environment‑aware configuration layer that keeps secrets out of source control and reduces runtime surprises.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.