
Reactive scaling means you resize a server after it has already started failing under load, not before. By the time RAM usage triggers the OOM killer or MariaDB starts rejecting connections, checkout pages are timing out, support tickets are piling up, and you are firefighting in production instead of executing a plan you made calmly weeks earlier.
The fix is not more monitoring alerts fired louder, it is a different posture: treat resource usage as a trend you forecast, not a status you check when something breaks. A 4 vCPU / 8GB / 150GB Ubuntu 22.04 box that is healthy today at 40% CPU and 55% RAM can be weeks away from saturation if traffic is compounding, and a single point-in-time reading of "everything looks fine" tells you nothing about that trajectory.
Four numbers matter for capacity planning, and all four need history, not a snapshot: CPU/RAM/disk usage over weeks, PHP-FPM pool utilization, database connection count, and traffic growth rate. A single "top" reading tells you the server is fine right now; it says nothing about whether it will still be fine in six weeks.
Running these commands once tells you today's number. Running them weekly and logging the output — or better, graphing it — tells you the slope, and the slope is what you are actually planning around. PHP-FPM pool utilization above roughly 80% of pm.max_children under normal (not peak) traffic means the pool itself, not the server's raw CPU or RAM, will be your first bottleneck as traffic grows further.
You do not need to build a separate monitoring stack to get this history. CloudStick's dashboard already runs Zabbix Agent 2 on every server and plots CPU, RAM, and disk usage as trend graphs over time, so the exact data forecasting requires — where the line has been and where it is heading — is already sitting there without any extra setup.
An alert that fires at 95% RAM or disk usage gives you no time to act — you are already in the danger zone by the time it lands. Set your action threshold around 70-75% sustained usage instead, so a "resize soon" alert arrives while you still have room to plan a maintenance window rather than respond to an outage.
The word "sustained" matters as much as the number itself. A single spike to 90% CPU during a five-minute traffic burst is not a capacity problem, it is normal variance. What deserves attention is a baseline that has climbed from 45% to 70% over the last month and shows no sign of leveling off — that pattern, not a momentary spike, is the one that turns into an outage if left unaddressed.
Capacity planning is a projection exercise, and the only input that matters is your actual growth trend, not a guess. If traffic doubled over the last six months, the right planning assumption is that it keeps doubling on a similar timeline, not that it flatlines from here just because that would be more convenient to plan around.
Pull pageview or request growth from your analytics or access logs over the same period you are looking at resource trends, and line the two up. If RAM usage grew 25% while traffic grew 60%, your current stack is scaling sub-linearly and you likely have more runway than the raw resource numbers alone suggest. If RAM grew faster than traffic, something — an unbounded cache, a memory leak, a plugin — is degrading efficiency and needs fixing before you throw a bigger server at it.
Steady growth and sudden spikes are different problems, and your capacity plan needs margin for both. A launch, a viral post, or a marketing email blast can double traffic for a few hours with no warning, and a server sized to exactly match projected steady-state growth has nothing left to absorb that.
A workable rule for a small team: size for your projected sustained load six months out, then add another 25-30% on top as spike headroom, and keep that headroom untouched by day-to-day baseline growth. If your projected steady RAM need lands at 6GB, plan the resize toward roughly 8GB rather than exactly 6GB — the difference is what keeps a traffic spike from becoming a database connection storm or an FPM pool exhausting pm.max_children mid-event.
Capacity planning only works if it happens on a schedule, not only after something breaks. A small team without a dedicated SRE does not need a formal process — it needs a recurring 20-minute check that actually happens every month.
Monthly: open the CloudStick dashboard's CPU/RAM/disk trend graphs for each production server, note whether the baseline has moved since last month, and check PHP-FPM and database connection counts against their limits. This takes less time than a standup and catches slow creep before it becomes an incident. Quarterly: line up that resource trend against your actual traffic growth, decide whether the current server size still covers the next two quarters plus spike headroom, and schedule a resize proactively if it does not. That is the entire framework — no dedicated tooling, no separate monitoring stack, no SRE headcount required, just a recurring look at real trend data and a threshold that tells you when to act before, not after, a spike takes the site down.

