← Back to all articles
Challenges

Designing an Architecture That Scales from 1,000 to 100,000 Users

By Marc Molas·March 21, 2024·10 min read

"Premature optimization is the root of all evil." Everyone quotes Knuth. But there's a variant nobody mentions: premature ignorance about scalability is just as dangerous.

The goal isn't to build for 100,000 users from day one. That's over-engineering. The goal is to avoid making decisions at 1,000 users that make it impossible to reach 100,000 without rewriting everything from scratch.

I've seen startups spend three months designing a microservices architecture for a product that doesn't have its first customer yet. And I've seen startups hit 10,000 users and have to freeze feature development for two months because their database is dying and their architecture can't scale horizontally.

Both extremes are avoidable. Here's a realistic roadmap of what you need at each stage.

Phase 1: 0 to 1,000 Users — The Well-Built Monolith

At this stage, your priority is the product, not the infrastructure. You need to validate that what you're building makes sense, iterate fast, and not waste energy on problems you don't have yet.

The right architecture here is simple:

  • A monolith. Rails, Django, Express, Laravel, Next.js. Whatever your team knows best. One repo, one deploy.
  • PostgreSQL. Probably the safest database decision you can make. It supports JSON, full-text search, ACID transactions, and scales well up to hundreds of thousands of records with proper indexes.
  • One server. A VPS on Hetzner, an AWS instance, a Heroku dyno. A single server running your application and your database.
  • Simple deploys. Git push, basic CI/CD with GitHub Actions or GitLab CI. No containers if you don't need them.

What you SHOULD get right from the start:

  • Stateless application. Your app server should not store state in memory or on disk. Sessions go in the database or Redis, files go to S3. This is critical because when you need to add a second server, you can't have local state.
  • Database indexes. Every query that filters or sorts needs an index. This isn't premature optimization — it's basic hygiene. A query without an index that takes 50ms with 100 records takes 5 seconds with 100,000.
  • Separate business logic from the presentation layer. Even in a monolith, structure your code so that when you need an API for a mobile app, you don't have to rewrite your business logic.

Phase 2: 1,000 to 10,000 Users — The First Optimizations

This is where you start noticing the first bottlenecks. Pages load slower, the database starts struggling on certain queries, and long-running processes block requests.

What you need to add:

  • Redis caching. Don't cache everything at once. Identify the slowest or most-hit endpoints and cache their responses. A product page that runs 5 database queries and gets served 10,000 times a day is a perfect caching candidate.
  • CDN for static assets. Images, CSS, JavaScript. Cloudflare, CloudFront, Bunny CDN. This reduces your server load and improves load times for users in different regions.
  • Database read replicas. If your app is read-heavy (most are), set up a PostgreSQL read replica. Writes go to the primary, reads go to the replica. This doubles your read capacity without touching a single line of application code.
  • Background jobs. Everything that doesn't need an immediate response leaves the request/response cycle. Sending emails, processing images, generating reports, syncing with third parties. Celery for Python, Sidekiq for Ruby, BullMQ for Node.js.

The most common mistake at this stage: not monitoring. If you don't measure, you can't optimize. Set up something that gives you visibility into response times, slow queries, and resource usage. Nothing expensive — basic metrics from your hosting provider plus something like Grafana with Prometheus is enough.

Phase 3: 10,000 to 100,000 Users — Scaling Horizontally

This is where your architecture proves whether those early decisions were sound. If your application is stateless and your database has proper indexes, this transition is manageable. If not, brace yourself for weeks of refactoring.

What you need:

  • Load balancer + multiple app servers. Nginx, HAProxy, or your cloud provider's balancer. If your application is stateless (as it should be since Phase 1), this is just spinning up servers and pointing the balancer at them.
  • Serious database optimization. Connection pooling with PgBouncer. Slow query analysis with EXPLAIN ANALYZE. Composite indexes for the most frequent queries. Consider materialized views for heavy reports.
  • Separate resource-heavy services. If you have a process that consumes a lot of resources (image processing, PDF generation, complex calculations), move it to a separate service. This isn't a microservice in the architectural sense — it's simply offloading heavy work from the main process.
  • Message queues for async processing. RabbitMQ or Amazon SQS. For inter-service communication and to absorb traffic spikes. A surge in traffic shouldn't bring your system down if non-critical processes are in a queue.
  • Autoscaling. Set up rules so your app servers scale automatically based on CPU or request count. On AWS, that's an Auto Scaling Group. On Kubernetes, a Horizontal Pod Autoscaler (but you probably don't need Kubernetes yet).

The Decisions That Matter from Day One

If I had to boil it down to a single list of what to get right from the start, it would be this:

  • Stateless design. No state on the app server. Sessions in Redis or the database, files in external storage.
  • External session storage. Never store sessions in process memory. When you scale to multiple servers, a user could hit a different server on every request.
  • Index strategy. Every query that uses WHERE or ORDER BY needs an index. Review this periodically with the query planner.
  • Separate read and write patterns. Even if you don't have read replicas yet, structure your code so it's easy to point reads to a different connection when the time comes.
  • Reversible migrations. Every database schema change should be reversible. This isn't directly about scalability, but it prevents downtime when something goes wrong in production.

What NOT to Do

This is just as important as the above:

  • Don't shard your database at 5,000 users. Sharding is complex, introduces enormous operational overhead, and you probably won't need it until hundreds of thousands or millions of users. A well-configured PostgreSQL handles far more than you think.
  • Don't introduce Kubernetes at 10,000 users. K8s solves orchestration problems at scale. If you have 3-5 servers, Docker Compose or a simple load balancer with instances is more than enough. The operational complexity of Kubernetes isn't justified until you have dozens of services.
  • Don't build microservices before you have 3 teams. Microservices are an organizational strategy, not a technical one. If a single team maintains everything, microservices just add network latency, deployment complexity, and debugging pain.
  • Don't optimize without measuring. Every optimization should be backed by data. "I think the database is slow" isn't enough. "This query takes 800ms and runs 50,000 times a day" is.

The Checklist Before Each Growth Phase

Before moving to the next phase, verify:

  • Do you have monitoring that tells you where the real bottlenecks are?
  • Can your application run on multiple instances without issues?
  • Do the most frequent queries have proper indexes?
  • Are heavy processes outside the request/response cycle?
  • Can you deploy without downtime?
  • Do you have automated backups, and have you tested restoring them?

The Value of Scalability Experience

The difference between scaling with pain and scaling with confidence is having been through the process before. An architect who has already scaled a system from 1,000 to 100,000 users knows which patterns matter at each phase — and more importantly, which ones don't matter yet.

At Conectia, the senior engineers we connect with European startups have been through these phases on real products. They won't propose Kubernetes for your MVP or microservices for your four-person team. They'll help you make the right decisions for your current stage, while keeping the door open for the next one.

Because scaling isn't an event. It's a series of incremental decisions. And each one is much easier when someone on your team already knows what comes next.


Is your product growing and you're not sure your architecture can handle the next order of magnitude? Talk to a CTO — we connect you with architects who have already scaled systems like yours.

Ready to build your engineering team?

Talk to a technical partner and get CTO-vetted developers deployed in 72 hours.