Before you measure
Use a Linux test machine you control, with your application and representative data. The commands below inspect resources; they do not tune the kernel or delete files. You need procps and GNU coreutils, and permission to inspect the chosen application directory. Replace /srv/my-app with its real path. If the app is not running anywhere yet, use its development or staging environment to build an initial estimate, then revisit that estimate on the intended system.
Write down what shares the VPS: operating system, proxy, API, database, workers and monitoring. Record whether asset builds run there, whether backups are compressed locally, and whether a scheduled task can overlap a deployment. A quiet application process can coexist with an expensive release process.
Read available memory and identify the processes
free -m
ps -eo pid,comm,rss --sort=-rss | head -n 12
free -m reports mebibytes. Focus on available, the estimate of memory that could support new work without swapping; free alone excludes useful reclaimable memory. Cache is therefore not, by itself, a reason to buy more RAM. See the free field definitions.
Illustrative selected fields — not an OffVPS measurement
Mem total: 2048 MiB
Mem free: 180 MiB
Mem available: 800 MiB
Illustrative ps rows
PID COMMAND RSS
2100 postgres 393216
2140 node 184320
920 caddy 32768
The process RSS values above correspond roughly to 384, 180 and 32 MiB. They help locate memory use, but adding every RSS value is not an exact machine total: shared pages can be counted more than once and some kernel costs are outside the process figure. Avoid printing command arguments or environments when collecting a report, because they may contain secrets. The ps manual explains its fields and snapshot behavior.
Turn observations into a worksheet
The following allowances illustrate a small API with a local database and one worker. They are invented planning values, not benchmarks or minimum requirements for a particular framework. Substitute your measurements, and note which allowances can peak at the same time.
| Component or allowance | Illustrative RAM budget |
|---|---|
| OS and supporting services | 160 MiB |
| Reverse proxy | 32 MiB |
| API process | 180 MiB |
| Database | 384 MiB |
| Background worker | 96 MiB |
| Additional deployment work | 320 MiB |
| Growth and uncertainty allowance | 200 MiB |
| Planning total | 1,372 MiB |
This worksheet already exceeds a 1,024 MiB budget. A 2,048 MiB test environment would leave 676 MiB against these allowances, but the useful result is whether real representative work fits while the app remains responsive. If the deployment allowance dominates, building artifacts elsewhere may be a better change than enlarging the permanent server. Preserve the assumptions beside the total.
Watch CPU and swap during useful work
vmstat 1 10
Run this during a representative request batch, a job and a release. Ignore the first line when interpreting a recent interval: it summarizes activity since boot. Later lines describe the sampling intervals. Persistent runnable work in r, low idle time in id and slow requests together justify investigating CPU pressure. Repeated si/so activity shows swapping; allocated swap alone does not prove current pressure. wa and st need context rather than an automatic CPU upgrade. These fields are defined in vmstat.
Record response time at the application as well. A slow external API or database query can make requests wait while the CPU remains mostly idle. Repeat the same workload after one change, so that you know which change helped. Load tests should target only systems you control, with a rate and stop condition that avoid disrupting other users.
Budget disk growth and transfer separately
df -h /srv/my-app
df -i /srv/my-app
du -sh /srv/my-app
df describes the filesystem containing the path, including space shared with other directories; df -i checks inode use where supported. A large number of small files can exhaust inodes before byte capacity. du estimates the chosen tree, subject to access permissions. These are different questions, so their totals need not match. See df and du.
List the current database, uploads, logs, application artifacts and any local backup staging space. Add the space needed for a release alongside the previous release, then estimate growth over the next review interval. For example, 100 MiB of new uploads each day adds about 3,000 MiB over 30 days before replicas or backups. Label decimal GB and binary GiB consistently when comparing the result with a catalogue.
For transfer, an illustrative 20 kB response sent 50,000 times is about 1 GB of response payload. Add uploads, static files, protocol overhead and backup traffic. That arithmetic estimates volume, not throughput or simultaneous users. Confirm how the service counts traffic and handles any excess.
Choose the next action and check it
- Low available memory during normal peaks: inspect the main consumers and test a larger memory budget.
- Slow requests with sustained CPU pressure: profile the busy path, then compare CPU changes using the same workload.
- Growing disk use: identify the responsible directory and retention policy before deleting anything.
- Resources look comfortable but the app is slow: investigate dependencies, queries and the request path.
Save the worksheet with the workload description, sample time, units and next review date. Recheck after a substantial release, data growth or an added worker. Choose a configuration from those observations; no plan name guarantees request capacity. Continue with reading memory and disk warnings or the first API resource scenario.
Documentation used
Primary references for this page. Check the documentation for the version installed in your own environment.