Database Workloads Are Different
Databases have unique resource requirements. Unlike stateless web apps, databases are memory-intensive and I/O-bound. Getting sizing wrong leads to slow queries and connection timeouts.
The Golden Rule
Your working dataset should fit in RAM.
When frequently accessed data exceeds available memory, performance degrades as the database reads from disk instead of memory.
PostgreSQL Sizing
Based on PostgreSQL documentation ↗:
| Database Size | Connections | Recommended RAM | VPS Tier |
|---|---|---|---|
| < 1 GB | < 20 | 2 GB | Production |
| 1-5 GB | 20-50 | 4-8 GB | Production |
| 5-20 GB | 50-100 | 16-32 GB | Performance |
| > 20 GB | 100+ | 64+ GB | Enterprise |
Key PostgreSQL Settings
# postgresql.conf - typical starting points
shared_buffers = 25% of RAM
effective_cache_size = 75% of RAM
work_mem = 64MB # Adjust based on query complexity
maintenance_work_mem = 256MB
Note: These are starting points. Optimal settings depend on your specific workload. See PGTune ↗ for recommendations.
MySQL/MariaDB Sizing
Based on MySQL documentation ↗:
InnoDB Buffer Pool: Set to 70-80% of available RAM for dedicated database servers
Example: 4 GB VPS → ~3 GB buffer pool
# my.cnf - typical starting points
innodb_buffer_pool_size = 3G
innodb_log_file_size = 256M
max_connections = 150
Redis Sizing
Redis stores data in memory (documentation ↗). Size based on your use case:
Cache Only
512 MB - 2 GB
Session storage, query cache
Queue/Pub-Sub
1 - 4 GB
Job queues, real-time messaging
Primary Datastore
Size of dataset + overhead
Full dataset in memory
When to Separate Database Server
Run your database on a separate VPS when:
- Combined RAM needs exceed 4-8 GB — Competing for resources hurts both app and database
- You need independent scaling — Scale app and database separately
- High availability required — Replication and failover setups
- Multiple apps share the database — Centralized data layer
Connection Pooling
Always use connection pooling in production:
Without pooling: Each request = new connection = memory overhead per connection
With pooling: Shared connections = predictable, lower memory usage
Recommended tools: PgBouncer ↗ (PostgreSQL), ProxySQL ↗ (MySQL)
Size Your Database Server →