VPS with 16 GB RAM: in-memory databases, search and local AI models
Sixteen gigabytes is the size at which memory starts working as an accelerator rather than a constraint. The main reason to take it is data: a database that fits entirely in cache, a search index, analytics, a language model. If on 8 GB you were splitting memory between services, on 16 GB you decide which one gets the lion's share.
Workloads that call for 16 GB
- PostgreSQL or MySQL with a 10–30 GB database. The hot part of the data (active orders, users, indexes) fits in memory, and queries stop waiting on the disk. How to tune a server for a database is covered in the VPS for PostgreSQL section.
- Elasticsearch or OpenSearch on a single node: 8 GB goes to the heap, and Lucene needs the rest for the file cache. Indexes of up to several tens of gigabytes run at acceptable speed; see VPS for Elasticsearch.
- Language models on the CPU. A 7–8 billion parameter model in 4-bit quantisation takes 5–6 GB, a 13–14 billion one 9–10 GB. Both fit in 16 GB together with a web interface. Response speed will be limited by the CPU, not memory; details are in the VPS for Ollama section.
- 1C in client-server mode for 15–30 users: the 1C cluster and PostgreSQL on one machine.
- A Kubernetes node or a k3s test environment with a dozen microservices, monitoring and logging.
- A CI server that builds several Node.js, Java or Go projects in parallel.
16 GB becomes overpaying if the server hosts a set of small websites and bots: they don't need that much cache, and an 8 GB plan with the same number of cores will cope just as well. Before adding memory, look at where the current memory goes: the "shortage" often turns out to be a single leaking process or a database without indexes that reads whole tables. If the working data set really is growing faster than the buffer can hold, the next step is 32 GB or a separate database server.
How to allocate 16 GB for a database
For a dedicated database server the classic guidelines are: in PostgreSQL, shared_buffers around 4 GB (25%) and effective_cache_size 11–12 GB, because the kernel uses the rest for the file cache, which Postgres also reads from. work_mem is multiplied by the number of concurrent sort operations, so 64 MB across a hundred connections can easily eat all the memory: keep a connection pool via PgBouncer. For MySQL with InnoDB the buffer can be raised to 10–11 GB if there are no other heavy services on the server.
For Elasticsearch the rule is the opposite: the heap gets no more than half of memory, and the other half must stay free for the operating system cache. Setting the heap to 14 GB out of 16 is a common mistake that makes search slower, not faster.
Disk and cores at 16 GB
16 GB usually comes with 4–8 virtual cores and a 160–320 GB disk. For databases and search, choose only an NVMe VPS: memory speeds up reads, but writing the transaction log and merging index segments still hit the disk. For AI models the cores and their generation matter more: AVX2 or AVX-512 support speeds up model inference several times over, and you can check for it with grep -o 'avx[^ ]*' /proc/cpuinfo | sort -u.
Guaranteed memory, OOM and swap
The tasks people take 16 GB for cope badly with both container burst memory and swap. A database that has grown into non-guaranteed memory gets an OOM at the busiest moment when that memory is reclaimed; Elasticsearch, once its heap lands in swap, starts pausing for garbage collection for tens of seconds. So:
- take KVM with fully dedicated memory, not OpenVZ or LXC with burst;
- for Elasticsearch enable
bootstrap.memory_lock, and for Postgres setvm.overcommit_memory=2as the documentation recommends; - keep swap small, 2–4 GB, and make sure it doesn't grow.
Checks after purchase
free -handnproc: about 15.6 GB of memory and the number of cores stated in the plan.stress-ng --vm 2 --vm-bytes 14G --timeout 120s: the server should survive filling its memory without freezing.fiowith random 4 KB block writes: for a database this matters more than sequential read speed.- After a week of operation, compare the size of the hot data with the buffers: if the cache hit ratio in
pg_stat_databaseis below 99%, there isn't enough memory for the data.