Vertical scaling means running your application on a bigger machine: more RAM, more CPU, more disk, same one box. Horizontal scaling means running it on more machines at once, with a load balancer in front and the traffic split between them. Most applications never need the second one.
Horizontal scaling is more work than it looks, but that is not the main reason. One machine goes further than most people assume, and what horizontal scaling is usually bought for is only partly capacity.
How far one machine actually goes
The clearest public number still comes from Stack Overflow. In his 2016 architecture writeup, Nick Craver records a single day in February 2016: 209,420,973 HTTP requests hit their load balancer, 66,294,789 of which were page loads. Those were served by 9 primary web servers.
That is horizontal scaling, so it might look like an argument for the other side. Craver's own reading is more interesting. He writes that they were "down to needing only 1 web server", having "unintentionally tested this, successfully, a few times". Then he draws the line himself: "I'm saying it works. I'm not saying it's a good idea." They ran nine anyway, for "rolling builds, headroom, and redundancy".
His caveat is the point. Those were large physical servers, not a 4 GB VM, and years of optimization and a heavy caching tier sat behind those numbers. Your app may well be heavier per request. What transfers is not the request count. It is that a team serving 209 million requests in a day ran nine machines for reasons that were, by Craver's account, mostly not capacity.
What horizontal scaling actually buys
Three things, and they do not have the same answer.
Capacity past one machine's ceiling. Real, but worth testing against your own numbers first. If your sustained load genuinely exceeds the largest machine you can rent, you have no choice.
Redundancy. If the host fails, everything on it fails at the same time. Only a second machine in a different failure domain fixes that, and no amount of vertical scaling substitutes for it. This is the argument that actually holds.
Deploys without a gap in service. The requirement here is multiple instances, not multiple machines. The Kubernetes tutorial on rolling updates makes it explicit: running multiple instances "is a requirement for performing updates without affecting application availability." It says instances, not hosts. In a Kubernetes cluster they are normally spread across machines, but the requirement itself is satisfied by two containers on one host.
Coolify, which is what MapleDeploy runs, does this on a single server. On deploy it starts the new container, waits for its health check to pass, and only then stops the old one. New applications start with health checks off, so it is something you turn on rather than something you inherit, and Coolify's documentation treats a configured and passing health check as a requirement for rolling updates. So "zero-downtime deploys" is a weak argument for a second machine. Surviving the loss of the machine is the strong one.
Horizontal scaling is not a setting you turn on
Running more than one instance changes what your application is allowed to assume.
The twelve-factor guidance on processes exists to make horizontal scaling possible, and it states most clearly what that costs up front: "Twelve-factor processes are stateless and share-nothing", and "Sticky sessions are a violation of twelve-factor and should never be used or relied upon." In practice that means session state moves to a shared store, uploaded files move to object storage rather than the local disk, in-process caches stop being reliable, and scheduled jobs need a way to not run five times.
Then there is the database, which usually does not scale out the same way. Adding web servers is comparatively easy. Splitting writes across database nodes is a different project, and the usual first answer is a bigger database machine with read replicas rather than a distributed cluster.
None of this is a reason to avoid horizontal scaling when you need it. It is a reason not to build for it before you do.
The vertical path, concretely
Here is the ladder on MapleDeploy, with the actual steps and prices:
| Plan | RAM | vCPUs | Storage | Price (CAD) |
|---|---|---|---|---|
| Starter | 4 GB | 2 | 35 GB | $45/mo |
| Pro | 8 GB | 4 | 70 GB | $95/mo |
| Ultra | 16 GB | 6 | 125 GB | $195/mo |
| Ultra 32 | 32 GB | 8 | 250 GB | $395/mo |
| Ultra 64 | 64 GB | 8 | 500 GB | $695/mo |
Read the vCPU column. Cores double from Starter to Pro, then step to 6 and to 8, and stop. The last rung adds RAM and disk, not cores. If your workload is CPU-bound rather than memory-bound, the useful range of vertical scaling is narrower than the price range suggests.
Changing plans resizes the same VM in place rather than provisioning a new one and migrating you. Your apps and data stay where they are. The dashboard states the tradeoff before you confirm: "The server will experience a brief restart during the upgrade." It is not instant and it is not zero-downtime. We do not publish a guaranteed figure for how long the restart takes, because it varies with disk size.
Billing is not prorated: the current subscription ends and a new one starts at the new price immediately. The path also only runs upward. Downgrades are not supported, so moving to a smaller plan means creating a new server and migrating your data across. Size up when the evidence says so, not speculatively.
That evidence is in the dashboard, which shows CPU, memory, and disk usage per server and warns you when a resource crosses the alert threshold. Starter and Pro include a 30-day free trial, so you can make the first sizing decision against your real workload. Full details are in the pricing section.
Where the ceiling actually is
64 GB of RAM and 8 vCPUs is the top of this ladder. That is a real limit, not a soft one.
If your requirements run past it, one account can run more than one server, each billed separately. Our servers are all in the same Toronto facility, so a second MapleDeploy server buys capacity, not the separate failure domain the redundancy argument above calls for. Email us and we will tell you honestly whether we fit.
The signals of a genuine horizontal requirement are specific:
- Your uptime commitment has to survive the loss of a single host, and a brief outage during a reboot or resize is not acceptable to someone you have promised.
- Sustained CPU or memory load is near the top of the ladder, not spiky load that a bigger box would absorb.
- You need to serve users from more than one geographic region.
- A deploy failure or runaway process taking everything down at once has become an unacceptable risk rather than an annoyance.
On the first of those, we publish a 99.9% monthly uptime target with service credits, roughly 44 minutes a month. If your own commitment is tighter than that, or has to survive the loss of a host outright, one VM is not the architecture for it.
If none of those are true today, the machine you are on is not the constraint on your product. Consolidating onto one server and sizing it properly is usually the better use of an afternoon, and running several projects on one server covers how to size for the total.
The decision you can defer
Vertical scaling is a plan change and a restart. Horizontal scaling is an architecture. The first you can decide in an afternoon when the graphs tell you to. The second you decide once and then live inside.
The practical middle ground: keep session state out of process memory, keep uploads off the local filesystem, treat the local disk as scratch. That costs almost nothing while you are on one server, and it is most of the work if you ever need a second one.
Start on one server, size it when the graphs say so
Dedicated VMs in Toronto from 4 GB to 64 GB. 30-day free trial on Starter and Pro.