node-convict: schema-validated configuration for Node.js
Featureful configuration management library for Node.js
At a glance
- What is it?
- Convict puts a schema in front of your JSON, environment variables and command line, so a bad setting fails at startup instead of in production. Here is how the mechanism works, how to install it, and where it stops being the right tool.
- Who is it for?
- Adopt node-convict if your Node.js service has enough settings that silent typos in a config file have already cost you a deploy, and you want the schema to be the single place where each setting's type, default and allowed values live. Do not adopt it if you need live config reload without a restart, or if your settings are simple enough that a plain object literal is easier to read.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 148 days ago.
- What is it written in?
- Mainly JavaScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 28, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The failure convict is built to prevent
A Node.js service usually reads settings from a JSON file, a few environment variables and occasionally a command line flag. The values arrive as strings or loosely typed JSON, and nothing checks them until the code that uses them runs. A port arrives as the string "3000" instead of the number 3000, or a nested key is misspelled and silently falls back to undefined. The process starts, serves traffic, and fails on the first request that touches the bad value.
Convict's answer is to declare every setting once, in a schema, before any value is read. The README describes the goal as giving collaborators more context on each setting and enabling validation and early failures when configuration goes wrong. That is the whole pitch: the schema is documentation, type declaration and validation rule in one place, and the failure moves from request time to boot time.
The intended audience is a team rather than a solo script. The README frames the benefit around collaborators who may have less interest in digging through code to inspect or modify settings. If one person owns the whole service and the settings never change, the schema is overhead. If a config file is edited by people who did not write the service, the schema is the only thing standing between them and a typo that reaches production.
How the schema, the files and the environment combine
The mechanism is a precedence chain. You define a schema object where each key carries a default and a format, then convict loads values from several sources and merges them in a fixed order, with later sources overriding earlier ones. The README does not spell out the full precedence table, but the topics list on the repository (env, environment-variables, json, json-files) and the package layout confirm that JSON files and environment variables are both first-class inputs.
Validation happens per key against the declared format. Convict ships a set of built-in formats, and the monorepo carries two optional packages that extend them: convict-format-with-validator adds the email, ipaddress and url formats, and convict-format-with-moment adds duration and timestamp. That split matters. If you only need strings, numbers, booleans and enums, the main package is enough. If you need a URL to be checked as a URL, you install a second package and register the format.
Environment variables are the part that deserves scrutiny before you adopt. Nested schema keys have to be expressed as flat environment variable names, and the mapping between the two is a convention rather than something the type system enforces. A schema key nested two levels deep does not produce a compile error if your deployment sets the wrong variable name. It produces a default value, quietly. That is the same class of silent failure convict was built to remove, moved to the boundary between the schema and your deployment tooling.
The monorepo itself is managed through Lerna-Lite, with three workspaces: the main convict package and the two format packages. Installing the main package does not pull in the optional formats.
Installing node-convict and validating a first config
The project is published to npm as the convict package inside the mozilla/node-convict monorepo. The README does not include install instructions, so the package name is the only thing to go on: install the main package by name, and add the optional format packages only if you need those formats.
npm install convict
npm install convict-format-with-validator
npm install convict-format-with-momentThe first command installs the library. The second and third are the optional format packages described in the README's Packages section; skip them unless you need email, ipaddress, url, duration or timestamp validation.
The repository ships an example directory with example/config.json and example/server.js. Those two files are the shortest path to seeing the intended shape: a JSON file holding the values, and a server file that defines the schema and reads the merged result. The README does not reproduce the contents of either file, so read them in the repository rather than reconstructing them from memory.
What you should expect after wiring a schema in: passing a value of the wrong type, or a value outside an allowed set, stops the process during startup rather than at the first request. That is the behaviour the README promises with the phrase validation and early failures. If your process still starts with a malformed value, the schema is not covering that key.
Where convict gets in the way
The schema is not free. Every setting needs a declared default and format, and the schema becomes a second place to update whenever a setting changes. Teams that treat the schema as an afterthought end up with keys that exist in the JSON file but not in the schema, which convict cannot validate because it does not know about them. The schema only protects what you declare.
The bigger constraint is that configuration is read once, at startup. The README does not document a reload mechanism, and nothing in the repository layout suggests one. A service that needs to pick up a changed setting without a restart, such as a feature flag flipped by an operator, will not get that from convict. You restart the process or you build the reload path yourself.
The environment variable mapping is the third rough edge. Because nested keys flatten into variable names by convention, a mismatch between what the schema expects and what the deployment platform sets does not raise an error. It falls back to the default. On a platform where environment variables are configured through a web UI rather than a file under version control, that mismatch is easy to introduce and hard to notice.
Finally, the repository's licence metadata resolves to NOASSERTION rather than a standard identifier. The LICENSE file exists at the top level, but anyone who needs to know the exact terms before adopting the library has to read that file. The project was originally published under Mozilla's stewardship, and the LICENSE file is the authoritative source, not the repository metadata.
Convict against plain JSON config and node-config
The nearest comparison in the search data is node-config, which people also look for as Node-config JSON. The difference in approach is where the structure lives. node-config organises settings by deployment environment: you keep a default file plus per-environment files such as production or staging, and the library picks the right one based on an environment variable. Convict does not organise by environment name. It organises by schema, and environment variables are one input among several rather than the organising principle.
That means node-config is a better fit when the main problem is having a different set of values per deployment target and the values themselves are trusted. Convict is a better fit when the main problem is that the values are not trusted and you want a type and a range check on each one before the process serves traffic. They can be combined, but doing so means two systems deciding what a setting is worth, and the precedence between them becomes something you have to document yourself.
The other alternative is no library at all: a JSON file loaded with require and read directly. That is genuinely simpler, and for a handful of settings it is the right call. The moment a second person edits that file, or the moment a setting has a valid range, the missing validation starts costing more than the schema does.
Editorial conclusion
Adopt node-convict if your Node.js service has enough settings that silent typos in a config file have already cost you a deploy, and you want the schema to be the single place where each setting's type, default and allowed values live. Do not adopt it if you need live config reload without a restart, or if your settings are simple enough that a plain object literal is easier to read. Before committing, verify three things in your own environment: that the optional convict-format-with-validator and convict-format-with-moment packages cover the formats you need, that your deployment passes environment variables in the nested form convict expects, and which licence the LICENSE file in the repository actually carries, since the repository metadata does not resolve it to a standard identifier.
Frequently asked questions
What is node-convict and what does it do?
It is a configuration management library for Node.js that puts a schema in front of your settings. The README says it gives collaborators more context on each setting and enables validation and early failures when configuration goes wrong.
How do I install node-convict?
It is published to npm as the convict package in the mozilla/node-convict monorepo, so it installs with npm install convict. The optional email, ipaddress, url, duration and timestamp formats live in the separate convict-format-with-validator and convict-format-with-moment packages.
Does node-convict reload configuration without restarting the process?
The README does not document a reload mechanism and the repository layout does not suggest one, so configuration is read at startup. A changed setting requires a process restart.
What is the node-convict example in the repository?
The repository has an example directory containing example/config.json and example/server.js. The README does not reproduce their contents, so read those two files directly in the repository.
What licence does node-convict use?
The repository metadata reports NOASSERTION rather than a standard licence identifier, and a LICENSE file sits at the top level of the repository. Read that file for the actual terms.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/mozilla-node-convict)