Skip to content
ExponaBLOG
ENGINEERING CRAFT · DAY 099 / 100

Boring technology wins: a practical guide for developers

Proven tools let you spend innovation on the product.

Expona Admin6 min read

Boring technology wins: a practical guide for developers. Proven tools let you spend innovation on the product.

We've all felt the pull: a sleek new framework, a distributed database that promises sub-millisecond latency, a message queue built for streaming everything. The truth we've learned across e-commerce, CRM, trading, and SaaS is that boring technology wins. The companies shipping reliably and scaling sustainably aren't chasing the latest conference talk—they're building on Postgres, Redis, and a monolith, letting innovation flow where it actually matters: the product.

Postgres, Redis and a monolith go very far

We've shipped production systems serving millions of transactions using three core technologies: Postgres as the source of truth, Redis for caching and session management, and a monolithic application server. This stack isn't boring because it's old; it's boring because it works.

A single Postgres instance handles most workloads we encounter. With proper indexing, query optimization, and connection pooling, a well-configured Postgres cluster can handle hundreds of thousands of requests per second. We've seen teams move away from it only to regret the added complexity later. When Postgres hits a genuine ceiling—and that's rare in practice—replication, read replicas, and partitioning buy years more runway.

Redis sits in front of Postgres for three specific purposes: session storage, rate limiting, and computed caches. It's not a primary datastore; it's a performance accelerator. This separation of concerns keeps debugging simple. If Redis goes down, your app degrades gracefully—a cache miss isn't a data loss.

The monolith—typically a NestJS backend, a Next.js application, or a single .NET service—keeps your business logic in one place. No distributed transactions, no eventual consistency puzzles, no messages mysteriously lost in flight. The code that books a flight, charges a card, and records the transaction lives in one codebase with synchronous boundaries and shared domain models.

Consider a travel booking system we helped scale. It started with Node.js + Postgres + Redis. At 50 requests per second, one engineer could reason about the entire system. At 500 requests per second, it was still one engineer handling operational incidents because the system was simple enough to debug end-to-end. We scaled it to 5,000 RPS by adding a second Postgres replica and improving index usage—no architectural overhaul required.

Fewer moving parts, fewer incidents

Every service you add is another thing that can fail. Every asynchronous boundary is a source of eventual consistency bugs. Every database is another schema to migrate. We've learned this the hard way.

A monolith with Postgres and Redis has three potential failure modes (database, cache, application). A microservices architecture with Kafka, gRPC, three databases, and service discovery has thirty. Each one requires monitoring, alerting, retry logic, circuit breakers, and incident response playbooks.

We once worked with a SaaS team that split their monolith into eight microservices to "scale better." They went from two operational incidents per quarter to two per week. The incidents weren't about CPU or memory; they were about eventual consistency, Kafka lag, message replay logic, and cascade failures across service boundaries. They spent eighteen months porting back to a monolith with judicious Postgres optimization. That's real cost.

When you own fewer moving parts, you own the entire system. You can trace a request from HTTP to database commit without crossing organizational boundaries. You can run integration tests that actually test the whole flow. You can deploy a fix in thirty minutes instead of coordinating six teams.

This doesn't mean you never scale beyond a monolith. It means you don't split until you have clear evidence that splitting solves a real problem—not a theoretical one. We've helped teams add worker processes (Node.js workers in one app) or async job queues (Bull or similar in Redis) without breaking the monolith apart. You can handle 90% of distributed work with a single codebase that shares its database.

Easier hiring and onboarding

A new engineer starts on Monday. With boring technology, they can run the entire system locally by Wednesday. With a complex microservices setup, they're still spinning up services and debugging dependency issues by Friday.

We hire for problem-solving ability, not for Kafka expertise or distributed systems mastery. When your stack is Postgres, Redis, and a monolith, you can interview smart people who've never touched Redis before and bring them to productivity in two weeks. If your stack requires specialized knowledge—consensus algorithms, event sourcing, CQRS patterns—you've narrowed your hiring pool and increased your hiring time and cost.

Onboarding is also about retention. A junior engineer who understands the entire system after two weeks ships features faster and stays engaged. A junior engineer drowning in microservices complexity, waiting for infrastructure teams to provision resources, burns out and leaves.

Consider documentation. A monolith with a single database has one schema to document. The data flow is linear: request comes in, business logic runs, data persists, response goes out. A microservices architecture requires architecture diagrams, event choreography documentation, eventual consistency guarantees, and compensation logic explanations. That's not documentation that makes people productive; it's documentation that prevents catastrophic mistakes.

Save novelty for your real differentiator

Innovation is a scarce resource. Your team has a fixed amount of energy and creativity per quarter. Spend it on what matters.

If you're building a ride-hailing app, your differentiator is matching algorithms, fraud detection, and pricing logic. It's not that you wrote your own distributed consensus protocol or chose an obscure database. If you're building e-commerce, your differentiation is personalization, search quality, and supply chain optimization—not your infrastructure choices.

Every engineer working on infrastructure is an engineer not working on the product. Every incident debugging Kafka broker failures is time not spent building features. Every architectural decision meeting about sharding strategies is energy not spent on the actual business problem.

We've seen the inverse pattern work beautifully: teams that locked down a boring stack early and committed to it gained competitive advantage through velocity. They shipped features three times faster than competitors because they weren't perpetually re-architecting. In travel and e-commerce, that velocity compounds. The team that ships personalization in Q2 doesn't ship it in Q1, but they learn, iterate, and ship an even better version in Q3. The team that's still debating technology choices never ships it.

This isn't an argument against using the right tool for the job. It's an argument for being extremely conservative about what "right" means. If Postgres genuinely can't run your queries fast enough—you've profiled, indexed, and optimized—then consider a read replica strategy first. If Redis isn't fast enough, consider a better memory-only data structure library before replacing it. Make boredom your first instinct, novelty your last.

Common mistakes

Premature optimization through architecture. Teams often switch to microservices or exotic databases because they think they'll need to scale, not because they currently need to. By the time a single Postgres instance actually becomes a bottleneck, you have the revenue and hiring budget to hire experts who can handle sharding or read replicas—and do it properly. Don't pay the complexity cost upfront.

Mistaking boring for static. Boring doesn't mean stale. Postgres is boring but actively developed and industry-standard. Redis is boring but widely used and well-understood. A Node.js or .NET monolith is boring but perfectly modern. You can use boring technology with current best practices: dependency injection, testing, type safety, monitoring.

Adopting boring just because it's boring. There are genuine cases where a more specialized tool wins. Real-time data streaming systems might benefit from Kafka. Trading platforms might need microsecond-latency databases. Machine learning pipelines might require something Postgres can't do. The question is: does your actual product need this, or does your architecture diagram need it? Only the former justifies the complexity.

Ignoring operational chops. Boring technology still requires solid operations. Postgres needs backups, monitoring, and disaster recovery. Redis needs persistence strategy decisions and memory tuning. A monolith needs load balancing and graceful shutdown. The boring stack is simpler to operate than the complex one, but not zero-effort. Make sure you have the operational maturity to support it.

Key takeaways

  • Postgres, Redis, and a monolith handle the overwhelming majority of real-world workloads with fewer moving parts and fewer incidents.
  • Simpler systems are easier to hire for, onboard to, and reason about—freeing your team to focus on product differentiation.
  • Every architectural choice should answer the question: does this solve a real problem today, or are we optimizing for a future problem we haven't reached yet?
  • Boring technology wins not because it's trendy or prestigious, but because it lets your team ship faster and operate with confidence.
  • Save your innovation budget for the features and problems that actually differentiate your product in the market.
ShareXLinkedInReddit

Found this useful? Support the writing.

Buy me a coffee
Written by
Expona Admin
Site administrator

Comments

Loading comments…

Leave a comment

Comments are reviewed before they appear. Be kind and stay on topic.

Related articles

Boring technology wins | Engineering Craft | Expona