Migrating production infrastructure? Get up to ₹10,000 in migration credits. Apply now
voroaDocs
Voroa Postgres

Flexible database plans: sizing storage and compute apart

Why a database's memory and its disk grow at different rates, how each one fails when it runs short, and how storage is sized on a Voroa PostgreSQL database.

What this covers

A database has two costs that grow at different rates. Memory and processor decide how fast it answers queries and how many connections it can hold. Disk decides how much data it can keep. A reporting database may hold years of rows and be queried twice a day; a session store may hold very little and be hit constantly. The two needs have no fixed relation to each other, which is why buying them separately is a thing databases do at all.

Voroa does not sell the two apart today. Every PostgreSQL instance type includes its storage, so the type you choose sets both the memory and the storage limit, and more of either comes from moving to a larger type.

This page is about the choice rather than the mechanics: which of the two axes a given problem is actually on, and what happens if you read it wrong.

The two axes fail differently

Storage fails at a line. A database has a fixed limit, the Storage section on the database’s Settings tab shows how much of it is in use, and a PostgreSQL database that passes about 95% of the limit is placed in read-only mode: reads keep working and writes are rejected. That is abrupt, but it is predictable. The figure only goes one way, a warning appears as it nears the limit, and you can see it coming weeks ahead. See managed database storage limits.

Memory has no such line. A database with too little memory keeps accepting every query and simply answers more slowly, because the rows it works with no longer stay in cache and are read from disk again and again. Nothing is rejected, no threshold is crossed, and no warning appears. The symptom arrives as “the application feels slow”, often months after the change that caused it, which is why memory pressure is so often blamed on application code instead.

Knowing which of the two failures you are looking at is most of the decision.

When storage is the axis

  • The Storage section is past 80%, or the database is already read-only.
  • What is growing is the amount of data you keep: event and audit tables, uploads, historical rows you are required to retain.
  • Queries are fine and the database is simply filling up.

More storage does nothing for query speed. If a database is slow but half empty, storage is the wrong axis and more of it will change nothing except the bill.

When compute is the axis

  • Queries that used to return quickly now take noticeably longer, while the query itself has not changed and the tables under it have grown.
  • Your application reports that connections are refused or exhausted at busy times. The number of connections a database accepts is a property of the instance type, so it rises when you move to a larger one. Storage never changes it.
  • Aggregates and reports over large tables are slow while single-row lookups by primary key are still fast, which usually means the working set no longer fits in memory.

Indexes are worth exhausting first, because a missing index is cheaper to add than a larger instance and often accounts for the whole difference. Once the query plans are sensible and it is still slow, memory is the axis.

Being wrong is not symmetrical

Over-buying either axis costs money every month, and that is the whole case for reading the two apart: a single bundled size has to be large enough for whichever of your two needs is the larger, so you pay for headroom on the axis you were never short of.

Under-buying is where the two part company. Running out of storage stops writes, which is loud, immediate, and fixed by raising the limit. Running out of memory produces an application that is merely slow, which is quiet, hard to attribute, and can be lived with for a long time before anyone measures it. Size storage close to what you need and watch it; leave more headroom on memory than you think you need, because nothing will tell you when it runs out.

PostgreSQL and Key Value differ here

This whole way of thinking assumes a database that keeps its data on disk and reads it into memory as needed, which is PostgreSQL. A Key Value (Redis) database holds its data in memory, so the size you choose is the memory and the memory is the limit, and the two axes are one. A Key Value database that fills up is not placed in read-only mode either; what it does is your choice — keep everything and refuse new writes, or drop the oldest keys to make room — once that choice is available on your instance. If it is not yet, the instance page will tell you rather than leave you looking for it.

What you can do today

Last updated August 21, 2026