When a junior engineer asks me “why are you bothering with Laravel, framework X is faster,” I start a conversation with a sigh. The answer is not “Laravel is better because Y.” The answer is this: “Every team has a limited complexity budget, and I prefer to spend it somewhere more important.”

What does “boring” mean?

Dan McKinley’s famous “Choose Boring Technology” essay popularized the term. “Boring” here is not bad — it means predictable, well-documented, and answerable from a Stack Overflow post written a decade ago when something breaks.

For me, the boring stack is:

  • PHP + Laravel or Symfony
  • PostgreSQL
  • Redis
  • Nginx
  • Linux + systemd + Supervisor

When I add a new one — say RabbitMQ — it takes 12–18 months of active production use before I’ll move it into the boring category. Until then it’s experimental, suspect.

The “innovation token” idea

In the same essay McKinley uses a metaphor called the innovation token: every team has a limited number of tokens to spend on innovation. Choosing a new language is a token. Choosing a new DB is a token. A new deployment platform is a token.

For a typical small team the budget is: 3 tokens.

When you spend them on:

  • A new programming language
  • A new type of database
  • A new messaging system
  • A new orchestration platform

you have no tokens left for the product itself — for the complexity that actually produces value.

Where do I spend my three tokens?

On most projects I spend these three:

  1. Domain complexity. Business rules, distributed workflows, eventual consistency — these eat budget because the work requires it.
  2. A new piece of infrastructure (e.g. adding a message broker, adding a search engine). Once a year at most.
  3. A small slice of an interesting experiment — building one feature with a new tool to see what we learn. Most of the time it gets thrown away again.

Everything else is proven.

A first-world problem?

No. The case for boring tech matters most precisely when our resources are limited. When big companies say “we’re moving all our flows to GraphQL,” some fraction of 200 engineers is working on it. Your 3-person team doing the same = 3 months of not building features.

”But this infrastructure is old”

PostgreSQL has been around since 1996. PHP since 1995. Nginx since 2004. Redis since 2009.

“Old” is not the right word — mature is. Mature software:

  • Has its edge cases discovered and fixed.
  • Gives error messages that return an answer when you Google them.
  • Lets a new team member be productive on their first day.
  • Doesn’t make “who created this bug” trace back to your library version.

Where are my exceptions?

  1. When a feature can’t be built with a proven tool. Example: CRDTs for real-time collaborative editing — this isn’t a mature space, and you don’t want to write it from scratch.
  2. When everyone on the team is experienced with the new tool. If 5 engineers have been writing Go for years, forcing them onto PHP is wrong.
  3. When the performance requirement is clear and measured. Not the hypothesis “it’ll be faster,” but the demonstration “there’s a bottleneck here, language X solves it.”

Conclusion

Building new technology is exciting. Running old technology is boring. The difference between those two is the difference between a 2-year-old product in production and a 6-month-old one. Choose based on whichever side you care about — but make the choice knowingly.

Boring tech is not cowardice, it’s a budget decision. Spend your budget on more valuable problems.