Almost every web application, whether a WordPress site, a SaaS product or an API, is built from the same few building blocks. Understanding them helps you deploy on a single VPS today, find bottlenecks, and know which piece to split out when traffic grows.

The building blocks

Component Job Common choices
Client Browser or mobile app; renders UI HTML, React, Vue, mobile apps
DNS and CDN Route users; cache static files near them Cloudflare, other CDNs
Reverse proxy / web server TLS, static files, routing, compression Nginx, Caddy, Apache
Application server Business logic, renders pages or JSON PHP-FPM, Node.js, Gunicorn/Uvicorn, Go, Java
Database Durable data MySQL, PostgreSQL, MongoDB
Cache Fast access to hot data and sessions Redis, Memcached
Queue and workers Background jobs (email, images, reports) Redis queues, RabbitMQ, Celery, BullMQ
File / object storage Uploads, media, backups Local disk, S3-compatible storage
Observability Logs, metrics, errors, uptime Prometheus, Grafana, Loki, Sentry

A request typically flows: DNS → (CDN) → Nginx → app server → cache or database → response. See reverse proxy on a VPS.

Stage 1: everything on one VPS

Users → Nginx → App (PHP-FPM / Node / Python) → MySQL or PostgreSQL
                                             → Redis

This is the right starting point for most projects. It’s cheap, simple to operate, and has no network latency between components. A 2–4 GB VPS runs a surprisingly busy site with good caching.

Do these from the start, because they make later steps easy:

  • Run each component as a separate service (systemd units or Docker containers). See Docker Compose in production.
  • Keep configuration in environment variables, not code.
  • Store uploads in one directory (or object storage) that can move later.
  • Automate backups, and test restores. See database backup automation.
  • Monitor CPU, RAM, disk, and response times. See observability basics.

Stage 2: add caching and background jobs

When pages get slower:

  • Page cache (Nginx FastCGI cache, Varnish) for anonymous pages. See Nginx FastCGI cache.
  • Object cache (Redis) for expensive queries and sessions. See Redis as a cache.
  • Queue slow work (emails, image processing, exports) to background workers, so web requests stay fast. See background jobs.
  • CDN for static assets. See CDN for websites.

Caching often gives a 10× improvement before you need more servers.

Stage 3: separate the database

Move the database to its own server when it competes with the app for RAM and CPU. The database gets dedicated memory for its buffer pool, and the app servers become stateless. Connect them over a private network, or over a firewall-restricted connection. See MySQL remote access and PostgreSQL remote connections.

Stage 4: multiple app servers behind a load balancer

Users → Load balancer (Nginx / HAProxy) → App server 1
                                       → App server 2  → Database (primary + replica)
                                                        → Redis

Requirements for this step:

  • Stateless app servers: sessions in Redis or the database, uploads in shared or object storage.
  • Identical deployments to every server (CI/CD).
  • Health checks in the load balancer.

See Nginx load balancing, HAProxy, and vertical vs horizontal scaling.

Stage 5: database scaling and high availability

Most applications never need sharding. Good indexes and caching go a very long way. See database indexing basics.

Monolith or microservices?

Splitting the application into many services is an organizational choice as much as a technical one. Most teams do best with a well-structured monolith, extracting services only where there’s a clear reason. See monolith vs microservices.

Common bottlenecks and fixes

Symptom Likely bottleneck Fix
High TTFB, CPU busy App code, no caching Page/object cache, profiling
Slow queries, high disk I/O Database Indexes, buffer pool, query fixes
Requests queue up Too few workers More PHP-FPM/Node workers (if RAM allows)
Spikes break the site Capacity Caching, CDN, load-test, scale out
Slow page loads for distant users Latency CDN, server location

Measure before you scale. See load testing with k6 and VPS performance troubleshooting.

Quick reference

Stage Setup
1 One VPS: web + app + DB + cache
2 Add page/object cache, queues, CDN
3 Database on its own server
4 Load balancer + stateless app servers
5 Replicas, pooling, HA

Related: Kubernetes vs Docker Compose and load balancer types.

  • Architecture
  • DevOps
  • Web Development