I’ve burned entire afternoons staring at YAML files, shuffling environment variables, and bickering with teammates about the “right” way to wire up a project. Most of that time was a complete write-off. The real problem wasn’t the settings themselves—it was the quiet assumption that everything deserved a setting. Configuration, when you lean on it too hard, turns into a brain tax. Convention, done well, is a relief. This isn’t an abstract argument; it’s a practical call that determines whether your team ships features or just ships configs.
What Configuration Actually Costs You
Configuration is tempting because it whispers flexibility. You tell yourself, “I’ll make this configurable, and anyone can tweak it later.” But flexibility is never free. Every knob you add is a decision point. Multiply that across a dozen services, and you’ve cooked up a combinatorial explosion of possible states. Most of those states never get tested, never get documented, and lie in wait for a 3 a.m. incident.

I once walked into a project that sported a 200-line JSON config file. It dictated everything—database retry logic, button colors, you name it. The team had burned weeks building a “configuration management system” just to validate that monster. Meanwhile, the actual product had flatlined. The config was a monument to indecision. Nobody wanted to commit to a firm choice, so they made everything a choice. The result? Paralysis for new developers and a debugging hellscape for the old hands.
The Hidden Weight of Explicit Settings
Explicit configuration piles on a documentation burden. You’ve got to explain what each knob does, which values are legal, and what happens when you mix them. In practice, that documentation rots quietly. Then you lean on tribal knowledge. Then the keeper of the tribal knowledge quits. Suddenly your “flexible” system is just a minefield with a pretty label.
There’s a cognitive tax too. Every time I crack open a project and see a sprawling config, my first thought is, “What do I actually have to touch to make this thing run?” I don’t want a buffet of options. I want sane defaults. I want the system to look me in the eye and say, “This is how we do things. If you hate it, you’re on your own.” That sounds cold, but it’s honest. And honest systems are easier to reason about.
Convention as a Force Multiplier
Convention means you make a decision once and stick with it. Ruby on Rails hammered this home with “convention over configuration.” Controllers live in app/controllers, models in app/models, views in app/views. You don’t configure those paths. You just know them. That predictability lets you jump into any Rails project and find your bearings in seconds.

I’ve taken that same idea into microservice architectures and frontend component libraries. In one team, we agreed that every service would expose a health check at /health, log JSON to stdout, and use environment variables prefixed with the service name. No config library, no ceremony. We just did it. The convention was so boring it didn’t need enforcement. New services fell in line because it was less work than inventing a new pattern.
When Convention Falls Apart
Convention isn’t a religion. It breaks sometimes. If your domain honestly has divergent needs—say, one service genuinely requires a different auth mechanism—then forcing a convention just creates friction. The skill is knowing when the exception is real. I run a dead-simple rule: if I’m the only one grumbling about the convention, I shut up and deal. If three people independently trip over it, the convention is wrong. Then we change it and migrate everything.
The worst outcome is a half-baked convention littered with escape hatches. That’s just configuration wearing a smug mask. Either commit to the convention or admit you need configuration. Don’t try to straddle both.
Practical Ways to Shrink Your Configuration Surface
Start by auditing your current projects. List every configurable parameter. For each one, ask: “Has anyone actually changed this from the default in the last six months?” If the answer is no, hardcode the default and rip out the config. If the answer is “yes, but only in one environment,” think about making that environment the exception instead of a universal knob.
Another trick: lean on runtime detection over static config. Instead of a MAX_THREADS setting, query the number of available CPUs. Instead of a LOG_LEVEL env var, default to info and flip to debug when a flag file exists. This shrinks the surface area for misconfiguration.

Naming Conventions Are Conventions Too
Never underestimate the power of naming things consistently. I’ve watched teams burn hours arguing over user_id versus userId versus user-id. Pick one, write it down in a README, and let a linter enforce it. This isn’t about aesthetics; it’s about cutting the mental overhead of context-switching.
At one job, we took a “config by convention” approach to database migrations. Every migration file followed a timestamp plus verb_noun pattern. We never had to configure ordering. The tooling just scanned the directory. It was boring and predictable. That’s about the highest compliment I can give a system.
Configuration Isn’t Evil—It’s Just Overprescribed
I’m not saying you should ditch configuration files entirely. Secrets, feature flags, and environment-specific endpoints genuinely need to vary. The trouble is we reach for configuration as the default when convention should be the reflex. Configuration ought to be the last resort, not the first instinct.
Think of it this way: every time you add a config option, you’re admitting you don’t know the right answer. Sometimes that’s honest. But if you do it too often, you’re just dodging the responsibility to decide. Make the call. Ship it. If you’re wrong, fix it later. That’s why version control exists.
The Social Side of Convention
Convention is a social contract. It only works if the team buys in. I’ve seen conventions crumble because one senior dev dug in their heels over personal preferences. The antidote is to make the convention so utterly boring that arguing against it feels petty. “We put all tests in a tests/ directory because that’s where tests go.” That’s not a technical argument; it’s a cultural one. And culture beats documentation every time.
If you’re introducing a new convention, skip the manifesto. Just start doing it. When someone asks why, say, “It’s simpler this way.” Most people will follow if it makes their life easier. The holdouts are usually fighting a different battle altogether.
FAQ
What’s a concrete example of convention over configuration in a modern stack?
Look at Next.js. You drop pages in the pages/ directory, and routing just works. No route table to configure. You can override it if you absolutely must, but the convention covers 95% of real-world needs. That’s the sweet spot.
How do you handle configuration that legitimately varies per environment?
Limit it to what’s truly environment-specific: database URLs, API keys, maybe logging verbosity. Keep that list brutally short. Use a single source of truth like environment variables, not nested YAML with inheritance hierarchies. If your staging and production configs differ in more than a handful of values, something’s probably off.
My team loves configuration. How do I convince them to adopt more conventions?
Don’t argue in the abstract. Find one painful config that breaks often or confuses newcomers. Replace it with a hardcoded default. Show that nothing bad happened. Then do it again. Small wins build credibility. Also, frame it as reducing work: “If we kill this config, we don’t have to maintain the validation logic.” Few engineers will argue against deleting code.
Isn’t convention just configuration hiding behind a name?
Yes and no. Convention is configuration that the system ships as a default—and you rarely need to touch it. The difference is intent. Configuration says, “You tell me.” Convention says, “I’ve got this; you focus on what matters.” It’s like a restaurant with a 20-page menu versus one with a daily special. I know which one gets my order right faster.
In the end, the whole configuration-versus-convention debate is really about trust. Do you trust your past self to make a decent call and move on? Or do you leave the door cracked open for every possible future, at the cost of present clarity? I’ve learned to trust my past self—warts and all—and to write conventions that let my future self think less and build more.