Start Simple
One server. One database. One deploy target. That is your architecture.
No Kubernetes. No event sourcing. No message queues. No service mesh. No data lake. No multi-region failover. Not yet. Maybe not ever.
The architecture that runs Hacker News is a single Lisp process on one server. It serves millions of pageviews. Craigslist ran on a few servers for years while facilitating billions of dollars in transactions. Stack Overflow serves 1.3 billion pageviews per month with a handful of servers and a monolith.
Simple architecture is not immature architecture. It is architecture that matches the actual needs of the system rather than the imagined future needs that may never materialize.
The Simplest Possible Architecture
For most startups at launch, this is the right architecture:
User -> Web Server -> Application -> Database
Components:
- One application server (Rails, Django, Next.js, Express)
- One PostgreSQL database
- One hosting platform (Heroku, Railway, Vercel, a single VPS)
- One domain
- HTTPS (handled by your hosting platform)
That's it.
No load balancer (one server does not need one). No cache layer (PostgreSQL is fast enough for your 12 users). No CDN (your static assets are fine served from your server). No background job system (cron or a simple in-process queue is enough).
Every additional component you add to this architecture is a component that can break, needs monitoring, needs updating, and needs to be understood by every engineer on the team. At a startup with two engineers, each additional component consumes a disproportionate amount of cognitive overhead.
The Complexity Budget
Think of architectural complexity like a budget. You have a limited amount of complexity your team can manage. Every component, every service, every integration consumes some of that budget.
Complexity budget for a 2-person startup:
Total budget: 100 units
Simple architecture:
- Application server: 20 units
- PostgreSQL: 15 units
- Hosting platform: 10 units
- Domain + SSL: 5 units
- Remaining: 50 units (available for product complexity)
Over-engineered architecture:
- Application server: 20 units
- PostgreSQL: 15 units
- Redis cache: 10 units
- Message queue: 15 units
- Kubernetes: 25 units
- Monitoring stack: 10 units
- CI/CD pipeline: 10 units
- Remaining: -5 units (in debt before writing product code)
The over-engineered startup spends its entire complexity budget on infrastructure. The simple startup spends half its budget on infrastructure and has the other half available for actual product development. The product is what users pay for. Infrastructure is overhead.
What You Do Not Need Yet
Kubernetes
Kubernetes is a container orchestration platform designed for companies running hundreds of services across thousands of servers. If you have one application and one database, Kubernetes is pure overhead.
The learning curve alone consumes weeks. Debugging Kubernetes issues is a specialized skill. When your pod fails to start at 2am, you will wish you had a simple server you could SSH into.
Kubernetes is appropriate when:
- You run 10+ services
- You need auto-scaling across many nodes
- You have a dedicated platform team
- Your deploy complexity justifies a platform
Kubernetes is overkill when:
- You have 1-3 services
- You have fewer than 10 engineers
- You do not have a dedicated platform team
- A PaaS (Heroku, Railway) solves your deploy needs
Message Queues
RabbitMQ, Kafka, SQS — these are for asynchronous communication between services. If you have one service, you do not need inter-service communication.
For background processing in a monolith, a simple job queue library is enough. Sidekiq for Ruby. Celery for Python. Bull for Node.js. These run in-process or alongside your application without a separate infrastructure component.
Message queue is appropriate when:
- Multiple services need to communicate asynchronously
- You need guaranteed delivery across service boundaries
- You process millions of events per day
Simple job queue is enough when:
- You need to send emails in the background
- You need to process uploads asynchronously
- You have occasional batch jobs
- You handle fewer than 100,000 jobs per day
Event Sourcing
Event sourcing stores every change to your data as an immutable event. It is powerful for audit trails, time travel, and complex domain modeling. It is also dramatically more complex than a standard database.
Unless you are building financial infrastructure or a system where a complete audit trail is a regulatory requirement, you do not need event sourcing. A regular PostgreSQL database with timestamps and soft deletes gives you 90% of the benefit with 10% of the complexity.
Caching Layer
Redis or Memcached as a caching layer is appropriate when your database is a bottleneck. For most early-stage startups, the database is not a bottleneck.
PostgreSQL can handle thousands of queries per second on modern hardware. If your queries are slow, the answer is usually better indexes or query optimization, not a cache layer.
Add a cache when:
- Specific queries take > 500ms despite proper indexes
- Database CPU is consistently > 70%
- The same expensive query runs hundreds of times per minute
Do not add a cache when:
- "It might be faster with caching"
- Your database CPU is at 5%
- You have fewer than 1,000 daily active users
Multi-Region Deployment
Running your application in multiple geographic regions adds enormous complexity: data replication, conflict resolution, routing, and cost. Unless your users are globally distributed and latency-sensitive, one region is fine.
Pick the region closest to most of your users. For US startups, that is usually us-east. For European startups, eu-west. Done.
Adding Complexity: The Evidence-Based Approach
The rule is simple: add complexity only when you have evidence that the simpler approach is failing.
Trigger: Response:
Database queries are slow Add indexes first. Optimize queries. Then consider caching.
Single server at 80% CPU Upgrade to a bigger server. Then consider horizontal scaling.
Deploys are slow Optimize your build. Then consider a separate CI service.
Background jobs are failing Fix the jobs. Then consider a dedicated job worker.
Users in Asia report latency Add a CDN for static assets. Then consider multi-region.
Notice that the first response is always the simpler option. Bigger server before more servers. Better indexes before cache layers. CDN before multi-region deployment.
This is the "scale up before you scale out" principle. Vertical scaling (bigger machines) is dramatically simpler than horizontal scaling (more machines). A single server with 32 cores and 128GB RAM handles an astonishing amount of work.
The "Boring" Architecture in Practice
Here is what a real startup architecture looks like at different stages:
Stage 1 — Pre-launch (0 users):
Vercel/Railway -> Next.js app -> PostgreSQL (managed)
Cost: $0-20/month
Stage 2 — Early traction (100-1,000 users):
Same as above, maybe a bigger database tier
Add: Sentry for error tracking
Cost: $20-100/month
Stage 3 — Growing (1,000-10,000 users):
Same app, bigger server
Add: Redis for session storage and job queue
Add: S3 for file storage
Add: CDN for static assets
Cost: $100-500/month
Stage 4 — Scaling (10,000-100,000 users):
Add: Database read replicas
Add: Dedicated background worker
Add: Load balancer with multiple app servers
Cost: $500-5,000/month
Stage 5 — Real scale (100,000+ users):
Now you might consider service extraction
Now you might consider Kubernetes
Now you might consider multi-region
Cost: $5,000+/month
Most startups never reach Stage 4. The ones that do have revenue to pay for the additional infrastructure and engineers to manage it.
Real-World Simple Architectures
Hacker News runs on a single server running Arc (a Lisp dialect). One process, one machine. It has served the tech community for over 15 years.
Basecamp runs on a handful of servers with a Rails monolith. They serve millions of users and generate tens of millions in annual revenue. They have written extensively about why they do not use microservices or cloud-native architecture.
Pinboard (bookmarking service) was run by one person on a few servers for years, generating hundreds of thousands in revenue. The architecture was deliberately simple because the operator was one person.
early Notion ran on a simple architecture despite being a complex product. They scaled their team and infrastructure only after finding product-market fit.
Common Pitfalls
Architecture astronautics. Designing for problems you do not have. If you are drawing architecture diagrams with 15 boxes before you have your first user, step back. You need one box and one database.
Confusing simple with fragile. A simple architecture is not a fragile architecture. A single server with proper backups, monitoring, and a deploy pipeline is more reliable than a complex distributed system with many failure modes.
Premature horizontal scaling. Running three small servers when one medium server would handle the load. Horizontal scaling adds coordination complexity. Vertical scaling is boring and effective.
Infrastructure as procrastination. Setting up monitoring dashboards, CI/CD pipelines, and staging environments instead of building your product. These are useful but not urgent when you have zero users.
Copying big company architecture. Netflix's architecture makes sense for Netflix. It does not make sense for your seed-stage startup. They have 10,000 engineers. You have 2.
Not adding complexity when needed. The flip side: if your database is falling over and your users are churning because of performance, it is time to add complexity. Simple is a starting point, not a religion.
Key Takeaways
- One server, one database, one deploy target. Start here. Add complexity only with evidence.
- Every architectural component consumes part of your complexity budget. Spend that budget on product features, not infrastructure.
- You do not need Kubernetes, message queues, event sourcing, or multi-region deployment. Not yet. Probably not for years.
- Scale up (bigger server) before you scale out (more servers). Vertical scaling is dramatically simpler.
- The most successful tech companies started with simple architectures. Complexity came later, driven by real problems.
- Add infrastructure when you have evidence of a specific problem, not when you anticipate a theoretical one.
- Simple architecture is not amateur architecture. It is architecture that matches your actual needs.