I spent six months building the perfect architecture for my first project. Redis for caching, Kafka for events, multiple database replicas, load balancers, auto-scaling groups, the works. We were ready for millions of users.
We got 12.
Six months of my life trying to set up the infrastructure instead of getting something out to users. Six months before learning that nobody actually wanted what we built.
Here's the thing nobody wants to admit: most of us are building for a scale we'll never reach, solving problems we don't have, optimizing for traffic that doesn't exist.
The "But What If We Go Viral" Trap
Every technical decision seems to start with "but what if we need to scale?"
What if we get on the front page of Hacker News? What if we suddenly have 100,000 concurrent users? What if our database can't handle the load?
So we do what any reasonable engineer would do. We prepare. We add Redis because "caching is important." We set up Kafka because "event-driven is the future." We deploy to multiple regions because "global users expect low latency." We add Elasticsearch because "search needs to be fast."
Meanwhile, our actual metrics look like this:
- Daily active users: 3 (you, your cofounder, your mom)
- Database queries per second: 0.1
- Server CPU usage: 2%
- Cache hit rate: 0% (because there's nothing to cache)
Real Companies That Scaled Without the Circus
Let me share some numbers that might hurt a little.
WhatsApp handled 450 million users with 32 engineers. No Kafka, no Redis cluster, just Erlang and FreeBSD.
Basecamp runs on a monolith. They've been profitable for decades. Millions in revenue, handful of servers. No multi-region deployment.
Stack Overflow handled 10 million daily visitors on 9 web servers. Not 90. Not 900. Nine. They didn't even use a CDN for years.
SQLite runs 35% of all websites. Not Postgres, not MySQL. A file-based database that fits on a floppy disk.
These aren't scrappy startups anymore. They're massive operations running on what most architects would call "legacy" or "unscalable" technology.
The Actual Cost of Premature Scaling
When you build for scale before you have users, you pay three prices.
The Money Cost:
Sure, you'll overpay for infrastructure you don't need. But let's assume you can afford it, so that's not the real problem.
The Time Cost:
Every piece of infrastructure you add multiplies complexity. A simple user signup becomes:
- Check Redis cache for existing user
- Write to primary database
- Replicate to read replicas
- Send event to Kafka
- Process event in separate service
- Update search index in Elasticsearch
- Invalidate relevant caches
- Sync to backup region
What could be one SQL INSERT becomes a distributed systems problem.
The Opportunity Cost:
This is the killer. While you're setting up your third AWS availability zone, your competitor shipped 10 features. While you're debugging why Kafka dropped messages, they're talking to customers. While you're optimizing Elasticsearch queries that run twice per day, they just used Postgres full-text search and moved on.
I see this constantly with UserJot users. The successful ones ship simple features fast. The ones who struggle are still debating whether they need Redis or Memcached.
When You Actually Need to Scale
Here's a simple test. You need to think about scale when:
- Your server response times are consistently over 500ms
- Your database queries are actually slow (measure first)
- You're spending more than $100/month on a single server that's maxed out
- You have actual users complaining about performance
Notice what's not on this list:
- "It might be slow someday"
- "What if we go viral"
- "Best practices say we should"
- "Netflix does it this way"
The Architecture That Actually Scales
Want to know a secret? The easiest architecture to scale is the simplest one.
Start with this:
- One server (Rails, Django, Node, whatever)
- One database (Postgres is fine)
- One deployment process (git push to deploy)
This setup can handle your first 10,000 users easily. Probably your first 100,000 if you're not doing anything crazy.
When you hit actual limits, here's what you do:
- Measure what's actually slow
- Fix that specific thing
- Repeat
Maybe that means adding Redis for specific cache needs (after you've proven you need it). Maybe it means a read replica for reports (after queries actually get slow). Maybe it means moving image processing to a background job (after it actually blocks requests).
But you add these things in response to real problems, not imaginary ones.
What This Looks Like in Practice
When I built UserJot, I decided to go against everything I'd learned as an engineer. No Redis, no message queues, no multiple databases, no global CDN, no multi-region setup. Just the simplest possible version.
The entire stack:
- TypeScript and Postgres
- Everything behind Cloudflare
- One repository
- One deployment
That's it. And it worked extremely well.
This setup handles:
- User authentication
- Payments through Stripe
- Email sending
- File uploads
- Real-time updates (using Postgres LISTEN/NOTIFY, not Redis pub/sub)
- Background jobs (using Postgres as a queue, not RabbitMQ or Kafka)
- Full-text search (using Postgres, not Elasticsearch)
- Vector search for similar feedback (using pgvector, not a separate service)
No Redis (Postgres can cache query results). No Kafka (Postgres can handle events). No Elasticsearch (Postgres has great full-text search). No separate databases for different data types (Postgres handles JSON, vectors, and relational data).
When something gets slow, we measure it, fix it, and move on. We don't preemptively add services because we might need them.
The Uncomfortable Truth About Your Scale
The harsh reality is that most of us will never need to scale past a single server. Even successful businesses often run on surprisingly simple infrastructure.
If you're building a SaaS product, you need about 1,000 paying customers to make a decent living. Most servers can handle 10,000+ users without breaking a sweat.
You're literally optimizing for a problem you'd be lucky to have.
How to Build Without the Scale Obsession
Here's my current playbook, learned the hard way:
Week 1-2: Prototype
- SQLite for the database (yes, really)
- Whatever framework you know best
- Deploy on the simplest platform (Railway, Render, whatever has a free tier)
- No Redis, no queues, no nothing
First 100 users:
- Move to Postgres if needed
- Add basic monitoring (just uptime is fine)
- Focus entirely on product-market fit
- Still no Redis, still no queues
First 1,000 users:
- Add error tracking
- Maybe add Redis if you have a specific bottleneck (measure first!)
- Start thinking about backups
- One region is still fine
First 10,000 users:
- Now you can think about architecture
- You have revenue to pay for infrastructure
- You have real usage patterns to optimize for
- Maybe now you need that cache layer
The Permission You Need to Hear
You don't need Redis yet.
You don't need Kafka.
You don't need Elasticsearch.
You don't need multiple databases.
You don't need multi-region deployment.
You don't need a CDN for your 50 users.
You don't need horizontal scaling.
You don't need database sharding.
You need to ship something people want.
All that complexity you're adding? It's not insurance against future problems. It's a guarantee of present ones.
My Challenge to You
Next time you start a project, try this:
- Use the most boring stack you know
- Deploy everything on a single server
- Use a single database for everything
- Don't add anything until you hit an actual limit
I guarantee you'll ship faster, spend less money, and probably never hit those limits anyway.
The simpler you build, the easier it is to scale when you actually need to. The complex architectures we build to handle scale often make scaling harder because there are so many moving parts to coordinate.
And if you need a feedback board to actually talk to those users you're building for instead of imagining scale problems, I'm building UserJot for exactly this. Simple tool, simple infrastructure, does what it needs to do.
Stop building for scale. Start building for users. The scale will sort itself out if you're lucky enough to need it.
Top comments (4)
And most importantly availability! More components are usually not great for uptime :)
Oh yeah! That's a really good point.
Love this, too many of us waste time scaling for users we don’t have.
You are a legend thanks for the advice!