Vertical scaling, which is also known as scaling up, involves increasing the resources of a single server, including CPU, RAM, and storage, to handle growing workloads. Even though it is a simple way and can boot performance quickly, vertical scaling will eventually hit limits in real production systems. This guide explains why vertical scaling fails, how to detect the warning signs early, and what architectural changes to make next.
If you're running on dedicated servers or VPS infrastructure, PerLod Hosting scaling solutions can help you transition smoothly.
Why Vertical Scaling Fails?
Vertical scaling usually works at the beginning, but in production, this approach hits hard limits and creates new risks, which is why vertical scaling fails over time. Whether you're on a VPS or dedicated server, understanding these limits helps you scale smarter.
Here are the most common reasons that vertical scaling fails:
1. Hardware and Physical Limitations: Every server has a maximum limit. Cloud servers can only get so big, and physical machines can only take a certain number of CPUs, RAM, and disks. Once you hit that limit, you can’t scale up anymore.
Key limitations include:
- CPU limit: Even the biggest cloud servers only offer a maximum number of vCPUs, so you can’t add more CPU.
- Memory limit: Physical machines can only hold so much RAM because the motherboard has a limited number of slots.
- Storage limit: Disks, even NVMe, and shared storage can only deliver a certain amount of IOPS and bandwidth, and you can’t push past that.
- Network limit: Network cards have a top speed, so at some point, the network becomes the bottleneck instead of CPU or RAM.
2. Single Point of Failure (SPOF): Putting everything on one server is risky. If that single machine goes down, because of hardware problems, an OS crash, or the app crashing, your whole service goes offline.
- Hardware failure of a CPU, memory module, or motherboard brings down all services.
- Software bugs or kernel issues affect the entire system simultaneously.
- Maintenance becomes harder because you often have to take the whole server offline to upgrade or fix it, which means full downtime. That downtime can affect SLA commitments.
3. Performance Bottlenecks and Diminishing Returns: Vertical scaling often creates new bottlenecks while solving old ones. Adding CPU cores won't help if disk I/O or network bandwidth becomes the limiting factor.
Common bottleneck scenarios include:
- Faster CPU, same slow disk or network: The CPU ends up waiting because data can’t arrive fast enough.
- More RAM, same system speed: Memory is bigger, but data still moves slowly inside the machine.
- Multi-CPU overhead: The server wastes time keeping all CPUs in sync.
4. High Cost and Economic Inefficiency:
Vertical scaling gets expensive fast. As you move to bigger premium servers, the price usually grows much faster than the performance, so you pay a lot more for a smaller gain.
5. Mandatory Downtime for Upgrades: Upgrading a single server usually means downtime. For physical hardware, you often must shut the machine down to add or replace CPU or RAM, and in the cloud, scaling up requires stopping and restarting the instance, so users see an interruption.
Typical downtime ranges include:
- Physical CPU and RAM upgrade: Around 30 minutes to 2 hours.
- Cloud instance resize: 5 to 15 minutes of unavailability.
- Storage migration: hours to days, depending on how much data you move.
6. Vendor Lock-in and Migration Complexity: When you keep scaling up, you may end up relying on special and expensive hardware or a specific cloud big instance type. That can make it harder to switch providers or move your workload later, because the setup and performance tuning don’t transfer cleanly.
Detect Vertical Scaling Failures
At this point, you can detect warning signs that vertical scaling fails, like rising CPU load, memory pressure, slow disk I/O, and longer response times, before the server hits its hard limit and the whole service becomes unstable.
1. CPU Monitoring Commands:
You can use the top command for real-time process monitoring.
top top -1 top -u apache top -b -n 1 | head -20
Key signs of CPU limits include:
- CPU usage stays high: User and system CPU are around 80% or more most of the time.
- Load is too high: Load average is higher than the number of CPU cores for long periods.
- High I/O wait: %wa is high, which usually means the CPU is waiting on disk or network, not doing real work.
You can use the htop command for enhanced visual monitoring:
sudo apt install htop sudo dnf install htop htop -t
Also, you can use the vmstat command for system-wide resource statistics:
vmstat 2 vmstat 1 10 vmstat -d 2
Essential signs of limitations include:
- r (run queue) > CPU cores
- us + sy > 80% for a while
- wa > 15%
- id (idle) < 10%
2. Memory Monitoring Commands:
You can use the free command for memory utilization:
free -h free -m watch -n 2 free -h
Warning signs that vertical scaling fails include:
- Available memory < 10% of total
- Swap usage > 0
- Buffer and cache are not reclaiming under load
You can use the vmstat command with the -s flag for memory indicators:
In the output, watch for:
- The swap used is increasing over time.
- The active memory is approaching the total memory.
3. Disk I/O Monitoring:
Use the iostat command to display I/O device statistics:
sudo apt install sysstat sudo dnf install sysstat iostat -x 2 iostat -xm 2
Warning signs that vertical scaling fails include:
- %util > 80% for extended periods
- await > 20ms
- avgqu-sz > 1
Also, you can use the df command to monitor disk space usage:
df -h df -i watch -n 5 'df -h /var/lib/mysql'
4. Network Monitoring Commands:
To monitor network connections, you can use the netstat command:
netstat -tuln netstat -an | grep ESTABLISHED | wc -l watch -n 2 'netstat -an | grep :80 | wc -l'
Use the ss command to display modern socket statistics:
For real-time bandwidth monitoring, you can use the iftop command:
sudo apt install iftop sudo dnf install iftop sudo iftop -i eth0
5. Application-Level Detection:
Thread Pool Monitoring: The case study showed how vertical scaling broke thread pool behavior. You can use the commands below to monitor thread utilization:
jcmd <PID> Thread.print | grep -c "Thread" jstat -gcutil <PID> 1000 ps -eLf | grep java | wc -l
Garbage Collection Pressure: When you give a Java service more memory, it can still run into GC problems, because the JVM may spend more time cleaning up a larger heap. To monitor and enable GC logs, use the commands below:
jstat -gc <PID> 1000 java -Xlog:gc*:file=/var/log/gc.log:time,level,tags
Warning signs include:
- FGC (Full GC) frequency is increasing.
- FGCT (Full GC time) exceeding 5% of total time.
Connection Pool Exhaustion:
mysql -e "SHOW STATUS LIKE 'Threads_connected';" psql -c "SELECT count(*) FROM pg_stat_activity;"
Automated Detection Script: You can create a comprehensive monitoring script with:
THRESHOLD_CPU=80THRESHOLD_MEM=90THRESHOLD_IO=80THRESHOLD_LOAD=0.8 echo "=== Vertical Scaling Limit Detection ==="echo "Timestamp: $(date)" CPU_IDLE=$(vmstat 1 2 | tail -1 | awk '{print $15}')CPU_USAGE=$((100 - CPU_IDLE))echo "CPU Usage: ${CPU_USAGE}%"if [ $CPU_USAGE -gt $THRESHOLD_CPU ]; then echo "WARNING: CPU usage exceeds threshold"fi MEM_INFO=$(free | grep Mem)MEM_TOTAL=$(echo $MEM_INFO | awk '{print $2}')MEM_USED=$(echo $MEM_INFO | awk '{print $3}')MEM_PERCENT=$((MEM_USED * 100 / MEM_TOTAL))echo "Memory Usage: ${MEM_PERCENT}%"if [ $MEM_PERCENT -gt $THRESHOLD_MEM ]; then echo "WARNING: Memory usage exceeds threshold"fi CORES=$(nproc)LOAD1=$(uptime | awk -F'load average:' '{print $2}' | awk '{print $1}' | sed 's/,//')LOAD_THRESHOLD=$(echo "$CORES * $THRESHOLD_LOAD" | bc)echo "Load Average (1min): $LOAD1 (Threshold: $LOAD_THRESHOLD)"if (( $(echo "$LOAD1 > $LOAD_THRESHOLD" | bc -l) )); then echo "WARNING: Load average exceeds threshold"fi if command -v iostat >/dev/null; then IO_UTIL=$(iostat -x 1 2 | awk '/^sda/ {print $NF}' | tail -1) echo "Disk I/O Utilization: ${IO_UTIL}%" if (( $(echo "$IO_UTIL > $THRESHOLD_IO" | bc -l) )); then echo "WARNING: Disk I/O exceeds threshold" fifi echo "======================================="
Kubernetes-Specific Detection: For containerized environments, you can use Vertical Pod Autoscaler (VPA) recommendations:
kubectl describe vpa <vpa-name> kubectl get vpa <vpa-name> -o yaml kubectl top pods --sort-by=cpu kubectl get events --field-selector reason=OOMKilled
VPA status signs of limits:
1status:2 recommendation:3 containerRecommendations:4 - containerName: app5 lowerBound:6 cpu: 500m7 memory: 1Gi8 target:9 cpu: 210 memory: 4Gi11 upperBound:12 cpu: 413 memory: 8Gi
When the target approaches your instance limits, vertical scaling is exhausted.
Next Steps After Vertical Scaling Hits Limits
Once scaling up hits hardware limits, becomes too risky, or stops improving performance, the next step is to change the architecture, not buy a bigger server. These are the common paths teams can take after vertical scaling fails:
Use Horizontal Scaling Architecture
You can distribute the workload across multiple servers instead of upgrading one. The implementation steps include:
Load Balancer Setup:
sudo apt install haproxy cat > /etc/haproxy/haproxy.cfg << 'EOF'global daemon maxconn 4096 defaults mode http timeout connect 5000ms timeout client 50000ms timeout server 50000ms frontend web_frontend bind *:80 default_backend web_backend backend web_backend balance roundrobin server web1 10.0.1.10:80 check server web2 10.0.1.11:80 check server web3 10.0.1.12:80 checkEOF sudo systemctl restart haproxy
Modify applications to avoid local state:
12def save_upload(file):3 with open(f"/tmp/{file.name}", "wb") as f:4 f.write(file.data)5 67def save_upload(file):8 s3_client.upload_fileobj(9 file.data, 10 "my-bucket", 11 f"uploads/{file.name}"12 )
12CHANGE MASTER TO3MASTER_HOST='master.example.com',4MASTER_USER='replica',5MASTER_PASSWORD='password',6MASTER_LOG_FILE='mysql-bin.000001',7MASTER_LOG_POS=107;8 9START SLAVE;
Session Management: Use external session stores:
sudo apt install redis-server echo "session.save_handler = redis" >> /etc/php/8.1/apache2/php.iniecho "session.save_path = tcp://127.0.0.1:6379" >> /etc/php/8.1/apache2/php.ini
You can learn more about horizontal scaling by checking this guide on Horizontal Scaling Strategies.
Use Hybrid Scaling Strategy
If vertical scaling fails, you can use vertical and horizontal scaling for optimal efficiency.
Vertical Optimization:
123kubectl apply -f - << 'EOF'4apiVersion: autoscaling.k8s.io/v15kind: VerticalPodAutoscaler6metadata:7 name: app-vpa8spec:9 targetRef:10 apiVersion: apps/v111 kind: Deployment12 name: app13 updatePolicy:14 updateMode: "Auto"15EOF
12kubectl apply -f - << 'EOF'3apiVersion: autoscaling/v24kind: HorizontalPodAutoscaler5metadata:6 name: app-hpa7spec:8 scaleTargetRef:9 apiVersion: apps/v110 kind: Deployment11 name: app12 minReplicas: 213 maxReplicas: 1014 metrics:15 - type: Resource16 resource:17 name: cpu18 target:19 type: Utilization20 averageUtilization: 7021EOF
Here is a suggestion for teams that usually want to move from vertical scaling to horizontal scaling as the user base grows:
| User Base |
Scaling Approach |
Timeline |
| < 100K users |
Vertical only |
1-3 months |
| 100K-1M users |
Hybrid (Vertical → Horizontal) |
3-6 months |
| > 1M users |
Horizontal mandatory |
6-12 months |
To learn more about Hybrid architecture, check this guide on building Hybrid hosting architecture.
Use Microservices Decomposition
Microservices decomposition means turning one big app into smaller services that can run and scale on their own. This helps after vertical scaling fails, because you can scale only the busy parts instead of upgrading one huge server.
Decomposition Strategy:
mkdir user-service && cd user-service
Conclusion
Vertical scaling is quick and simple, so teams start with it, but it will eventually hit limits, including hardware limits, higher costs, downtime risk, and hidden design issues. If you monitor CPU, memory, disk I/O, and app behavior early, you can plan before things break.
When vertical scaling fails, the fix isn’t a bigger server; it’s changing the architecture. Most teams move to horizontal scaling, a hybrid method, or microservices based on growth.
We hope you enjoy this guide on vertical scaling fails. Subscribe to our X and Facebook channels to get the latest articles.
For further reading:
Horizontal vs Vertical Scaling in Dedicated Servers.