- Databases are the one workload where "just add more CPU" rarely fixes performance problems — the real bottleneck is almost always disk I/O and memory allocated to buffer pools.
- This guide covers how to size a dedicated server for MySQL and PostgreSQL at real production scale.
Databases behave differently from almost every other workload you'll host: they are memory and disk I/O bound far more than CPU bound, they punish undersized RAM disproportionately because a cache miss means a disk read instead of a memory lookup, and they are the one component of a stack where downtime or data loss has the most severe consequences. Running MySQL or PostgreSQL on a properly sized dedicated server rather than a shared or under-provisioned VPS is one of the highest-leverage infrastructure decisions a growing application makes. This guide covers concrete sizing numbers, not just general tuning advice.
Why Databases Need Dedicated Hardware Sooner Than Web Tiers
A web/application tier degrades gracefully under resource pressure — requests queue and slow down. A database under memory pressure degrades far more sharply, because once the working set no longer fits in RAM (the buffer pool for MySQL/InnoDB, or shared_buffers plus OS page cache for PostgreSQL), every additional query increasingly hits disk instead of memory — and even fast NVMe is orders of magnitude slower than RAM for random reads. This is why database performance problems often look like a sudden cliff rather than a gradual slowdown.
RAM Sizing: The Most Important Number
The core principle for both MySQL/InnoDB and PostgreSQL: size RAM so your active working set (the data and indexes actually queried regularly, not necessarily your entire database) fits in memory.
| Database Size (Working Set) | Recommended RAM | MySQL innodb_buffer_pool_size | PostgreSQL shared_buffers |
|---|---|---|---|
| Under 10 GB | 16-32 GB | 10-16 GB (60-70% of RAM) | 4-8 GB (25% of RAM) + OS cache handles the rest |
| 10-50 GB | 32-64 GB | 24-40 GB | 8-16 GB shared_buffers, rely on OS page cache for the remainder |
| 50-200 GB | 128-256 GB | 90-170 GB | 32-64 GB shared_buffers |
| 200 GB+ | 256-512 GB, or shard/partition | Size to working set, not full dataset, if working set is smaller than total data | Consider partitioning and read replicas at this scale |
Note the difference in philosophy: MySQL/InnoDB wants a large buffer pool holding most of the "hot" data directly. PostgreSQL traditionally uses a smaller shared_buffers setting and relies heavily on the OS page cache as a second layer — this is a common point of confusion for teams moving between the two engines.
Storage: IOPS Matter More Than Capacity
Database workloads generate constant random reads and writes (index lookups, write-ahead log flushes, transaction commits) that punish slow storage far more than sequential-heavy workloads do.
| Workload | Storage Recommendation | Why |
|---|---|---|
| Small-to-mid OLTP application | NVMe SSD, RAID 1 | Low-latency random I/O for transactional reads/writes; RAID 1 for redundancy without excessive write penalty |
| High-write-volume OLTP (e-commerce, financial transactions) | Enterprise NVMe, RAID 10 | RAID 10 avoids the write-amplification penalty of RAID 5/6 under heavy write load |
| Analytics / reporting (OLAP-style queries) | NVMe with high sequential throughput, larger capacity | Large sequential scans across big tables benefit from raw throughput as much as IOPS |
A database server with plenty of RAM but slow storage still suffers badly during write-heavy operations (bulk inserts, index rebuilds, transaction log flushes) that cannot be served from cache — this is why storage sizing should never be an afterthought relative to RAM.
CPU Sizing for Database Workloads
CPU matters less than RAM and storage for most database workloads, but concurrency and query complexity still drive real requirements:
| Concurrency Level | CPU Recommendation |
|---|---|
| Under 100 concurrent connections, simple queries | 4-8 cores |
| 100-500 concurrent connections, moderate query complexity | 8-16 cores |
| 500+ concurrent connections, complex joins/aggregations, or heavy analytics | 16-32+ cores, consider read replicas to distribute load |
Replication and High Availability
Primary-Replica Replication
Both MySQL and PostgreSQL support native replication (MySQL binlog replication or Group Replication; PostgreSQL streaming replication) to a standby server, providing both a failover target and a read-scaling option by routing read-only queries to replicas.
Sizing Replicas
Replicas generally need matching or near-matching specs to the primary — a common mistake is under-sizing a replica assuming it does "less work," when in reality it must apply the same write volume as the primary while also potentially serving read traffic.
Backup Strategy for Dedicated Database Servers
- Logical backups (
mysqldump,pg_dump) — flexible and portable, but slow to restore for large databases; suitable for smaller databases or as a supplementary backup method. - Physical/binary backups (Percona XtraBackup for MySQL,
pg_basebackupfor PostgreSQL) — much faster restore times for large databases since they copy data files directly rather than replaying SQL. - Point-in-time recovery — combining a base backup with binary logs (MySQL) or WAL archiving (PostgreSQL) lets you restore to any specific moment, critical for recovering from accidental data corruption or deletion.
- Off-server backup storage — backups stored only on the same physical server provide zero protection against hardware failure; always replicate backups to separate storage or a separate location.
Common Database Performance Issues
- Slow queries despite "enough" RAM — often a missing index problem rather than a hardware problem; use
EXPLAIN(both engines) to verify queries are using indexes as expected before adding hardware. - Connection pool exhaustion — use a connection pooler (ProxySQL for MySQL, PgBouncer for PostgreSQL) rather than raising raw connection limits indefinitely, since each database connection carries real memory overhead.
- Replication lag under heavy write load — often means the replica's storage or CPU cannot keep pace with the primary's write volume; verify replica hardware matches or exceeds the primary's specs.
- Disk filling up from binary logs / WAL files — configure appropriate retention and rotation for binlogs/WAL, and monitor disk usage proactively rather than discovering the problem when writes start failing.
Database Dedicated Server Buyer's Checklist
- Is the storage NVMe, and is it configured in a RAID level appropriate for your read/write mix?
- Is there enough RAM headroom to grow the buffer pool/shared_buffers as your dataset grows, without an immediate hardware upgrade?
- Does the provider support easy addition of a replica server in the same or a different data center for HA/DR?
- Is ECC RAM used — memory errors on a database server can silently corrupt data in ways that are far more serious than on a stateless web tier?
- What is the actual disk failure/replacement SLA, and does the RAID configuration tolerate a single drive failure without downtime?
Frequently Asked Questions
How much RAM does my database server actually need?
Size RAM so your active working set — not necessarily your entire database — fits comfortably in the buffer pool/shared_buffers plus OS cache. Check your current buffer pool hit ratio; a hit ratio consistently below 99% for OLTP workloads usually signals you need more RAM.
Is MySQL or PostgreSQL better for a dedicated server setup?
Both perform excellently on properly sized dedicated hardware. The choice usually comes down to application ecosystem fit, specific feature needs (PostgreSQL's advanced data types and extensions vs MySQL's simplicity and broad tooling support), and team familiarity rather than raw hosting considerations.
Do I need SSD/NVMe, or is a large HDD array fine for a database?
For any transactional (OLTP) workload, NVMe is effectively mandatory at this point — the random I/O performance gap versus HDD is too large to ignore for production database workloads. HDD arrays may still make sense for cold backup storage, not live database files.
Should I put my application and database on the same dedicated server?
For small applications, yes — it is simpler and cheaper. Once either the application or database tier needs independent scaling, or you need the database isolated for security/compliance reasons, splitting them onto separate dedicated servers avoids resource contention between the two workloads.
How do I know if I need a read replica?
If read query volume is causing CPU or I/O contention that affects write performance, or you need geographic read distribution for latency, a read replica offloads read traffic from the primary. It does not help with write-scaling, which requires sharding or a different architecture.
What happens if my database server's disk fails?
With a properly configured RAID 1/10 array, a single disk failure is tolerated without downtime while the failed drive is replaced and rebuilt. Without RAID, a single disk failure can mean full data loss unless backups are current and accessible from elsewhere.
Database performance is won or lost on RAM sizing and storage IOPS, not marketing specs. WebsNP's dedicated server plans include NVMe storage and ECC RAM options suited for production MySQL and PostgreSQL workloads — contact our team for a sizing recommendation based on your dataset size and query load.