I've walked hundreds of clients through VPS migrations over the years. The same nine mistakes show up over and over, no matter which provider they picked or how carefully they read the marketing pages. Most of these errors don't reveal themselves until you're already running production traffic, and by then your options are limited.
Let's fix that.
Mistake 1: Choosing RAM and CPU based on shared hosting usage
Your cPanel shared hosting account used "unlimited" resources, so you assume 2GB RAM will be plenty for your VPS. Wrong assumption. On shared hosting the control panel, web server, database, mail server, and caching layers all ran on infrastructure you never saw. Now all of that sits on your VPS.
A basic WordPress site with WooCommerce, Redis, and email easily consumes 3-4GB at idle. Add traffic spikes and you're swapping to disk within an hour.
The correct approach: Start with 4GB minimum for a single production site. Monitor actual usage with htop and free -h for two weeks under real traffic. Scale up before you hit 80% memory utilization, not after your site goes down.
# Check current memory pressure
free -h
vmstat 1 5
# Look for high "si" and "so" (swap in/out) — that means you're out of RAM
CPU is more forgiving, but underpowered cores will make your admin panel unbearably slow during backups or updates.
Mistake 2: Skipping the kernel and OS update strategy
You provision an Ubuntu or AlmaLinux VPS and never touch the update settings. Six months later a privilege escalation vulnerability hits the news and you realize your kernel is eighteen months out of date. I've seen this end in compromised servers more times than I can count.
Unmanaged VPS means you own security patches.
The correct approach: Configure unattended upgrades for security patches on day one. Schedule monthly maintenance windows for kernel updates and the required reboot. Set up monitoring so you know when a reboot is pending.
# Debian/Ubuntu: enable automatic security updates
sudo apt install unattended-upgrades
sudo dpkg-reconfigure -plow unattended-upgrades
# RHEL/AlmaLinux: enable automatic security updates
sudo dnf install dnf-automatic
sudo systemctl enable --now dnf-automatic.timer
Kernel updates require a reboot. Plan for it. A scheduled two-minute maintenance window beats an unplanned six-hour incident response.
Mistake 3: Running SSH on port 22 with password auth enabled
Default SSH configuration is an open invitation. Bots hammer port 22 with dictionary attacks around the clock. Your logs will fill with failed login attempts within hours of going live, and if you picked a weak root password, they'll eventually get in.
The correct approach: Disable password authentication entirely and move SSH to a non-standard port. Use key-based auth exclusively.
# Generate an SSH key on your local machine (if you haven't already)
ssh-keygen -t ed25519 -C "[email protected]"
# Copy the public key to your VPS
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@your-vps-ip
# On the VPS, edit /etc/ssh/sshd_config
Port 2849 # pick any high port
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
# Restart SSH
sudo systemctl restart sshd
Test the new configuration in a second terminal session before closing your existing connection. If you lock yourself out, most providers offer an emergency console through their panel.
Mistake 4: Trusting the provider's backup solution without testing restores
Your VPS dashboard shows "Daily Backups Enabled" with a green checkmark. You assume that means you're protected. Then your database gets corrupted and you discover the backup system only captures disk snapshots, not application-consistent states. Your MySQL tables are half-written and won't start.
Or worse: the backup exists but the restore process takes nine hours and requires opening a support ticket.
The correct approach: Implement your own backup solution and test a full restore to a separate VPS before you need it. Provider snapshots are a safety net, not a primary solution.
# Example: daily MySQL dump + off-server copy
#!/bin/bash
BACKUP_DIR="/backup/mysql"
DATE=$(date +%Y%m%d_%H%M%S)
mkdir -p $BACKUP_DIR
mysqldump --all-databases --single-transaction --quick > $BACKUP_DIR/all_dbs_$DATE.sql
gzip $BACKUP_DIR/all_dbs_$DATE.sql
# Copy to remote storage (S3, rsync.net, another server)
rclone copy $BACKUP_DIR/ remote:vps-backups/
# Retain only last 7 days locally
find $BACKUP_DIR -name "*.sql.gz" -mtime +7 -delete
Schedule this via cron and run a test restore at least once a quarter. The restore test is the only way to know your backups actually work.
Mistake 5: Ignoring disk I/O limits and storage type
You ordered a VPS with 80GB SSD storage. Sounds fast, right? Not if the provider is using shared IOPS or network-attached storage with contention from other tenants. Your database queries start timing out under load and you can't figure out why the CPU and RAM graphs look fine.
Disk I/O is the silent killer on cheap VPS plans.
The correct approach: Test disk performance before committing to a provider. Compare sequential and random write speeds. Check if the provider publishes guaranteed IOPS or if they're shared/burstable.
# Quick disk write test (not scientific, but reveals obvious problems)
dd if=/dev/zero of=/tmp/testfile bs=1M count=1024 conv=fdatasync
# Should complete in under 2 seconds on decent NVMe, under 5 on SSD
# Random I/O test with fio (install via package manager)
fio --name=random-write --ioengine=libaio --rw=randwrite --bs=4k --size=1G --numjobs=4 --runtime=60 --time_based --end_fsync=1
If write speeds drop below 50 MB/s or random IOPS are under 1000, find a different provider or upgrade to a tier with local NVMe.
Mistake 6: Deploying without a firewall configuration
Your VPS comes online with every port open to the internet. You install a web stack, meaning you now have MySQL listening on 3306, Redis on 6379, and maybe an admin panel on 8080. All publicly accessible.
Attackers find exposed databases in minutes, not days.
The correct approach: Configure a firewall before installing anything else. Lock down everything except HTTP, HTTPS, and your custom SSH port. Open additional ports only to specific IP ranges when needed.
# Using UFW (Ubuntu/Debian)
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 2849/tcp # your custom SSH port
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
# Or firewalld (RHEL/AlmaLinux)
sudo firewall-cmd --set-default-zone=drop
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --permanent --add-port=2849/tcp
sudo firewall-cmd --reload
Never bind MySQL or Redis to 0.0.0.0 unless you have a specific reason and strong authentication. Use localhost or a private network interface instead.
Mistake 7: Selecting a provider based solely on price per month
You find a VPS for $4/month with specs that match competitors charging $20. Sounds like a great deal until you hit the network throttle at 1TB transfer, discover support tickets take four days to get a response, and realize the uptime SLA is "best effort" with no compensation.
In my support work, cheap VPS providers are the number one source of mysterious "my site is slow" tickets that turn out to be infrastructure problems the client can't fix.
The correct approach: Budget for mid-tier pricing from providers with a track record. Check recent reviews for support responsiveness and network reliability. Verify what the SLA actually covers and whether they publish a status page.
Test basics before moving production traffic: deploy a simple site, run a load test with a tool like ab or wrk, and open a test support ticket to measure response time.
Mistake 8: Running everything on one VPS with no failover plan
Your site, database, email server, and backup storage all live on the same VPS. When that VPS goes down for maintenance, has a hardware failure, or gets hit by a DDoS attack, everything stops.
Single points of failure aren't a question of if, they're a question of when.
The correct approach: Separate critical functions early. At minimum, keep backups on a different provider or object storage service. For high-availability setups, run your database on a managed service or a separate VPS with replication.
# Example: automate off-server backup to AWS S3
# Install and configure rclone, then:
rclone sync /backup/ s3-remote:my-vps-backup-bucket/ --exclude "*.tmp"
A complete failover setup requires load balancers and replicated databases, which is overkill for small projects. But knowing you can restore to a fresh VPS from external backups in under an hour makes a huge difference.
Mistake 9: Not monitoring resource usage and uptime
You assume your VPS is fine because the site loads when you check it. Meanwhile, your disk filled up three days ago and error logs stopped writing. Or your memory leak has been growing for two weeks and you're about to hit OOM killer during peak traffic.
What you don't monitor, you can't fix before it breaks.
The correct approach: Set up basic monitoring on day one. Track disk space, memory usage, CPU load, and HTTPS uptime. Get alerts before problems affect users.
# Quick monitoring with built-in tools
# Add to cron: check disk space every hour
0 * * * * df -h / | awk 'NR==2 {if (substr($5,1,length($5)-1) > 85) print "Disk usage high: " $5}' | mail -s "VPS Disk Alert" [email protected]
# Monitor memory
*/15 * * * * free | awk 'NR==2 {if ($3/$2 > 0.85) print "Memory high: " $3/$2*100 "%"}' | mail -s "VPS Memory Alert" [email protected]
For better visibility, install Netdata, Prometheus with node_exporter, or use a hosted service like UptimeRobot for external checks. Adjust thresholds based on your actual usage patterns after a week or two of baseline data.
What to check before going live
Run through this final checklist before pointing DNS at your new VPS:
- SSH is on a custom port with key-only auth
- Firewall is active and blocks everything except required services
- Automatic security updates are configured
- You've tested a full backup restore to a separate instance
- Monitoring and alerting are sending test notifications
- Disk I/O performance meets your application's needs
- Resource usage under simulated load stays below 70% of capacity
Every one of these nine mistakes is easy to make and expensive to fix after the fact. Most of them don't require advanced skills, just a checklist and an hour of setup time.
FAQ
How much RAM does a typical WordPress site need on a VPS?
Start with 4GB minimum. A stock WordPress install uses about 1.5GB with Apache and MySQL running. Add caching, plugins, and email services and you'll approach 3GB at idle. Traffic spikes push that higher. Monitor with htop and scale up before hitting 80% utilization.
Should I use my VPS provider's automated backup or set up my own?
Both. Provider snapshots are convenient for quick rollbacks, but test them and confirm recovery time. Run your own application-level backups (database dumps, file archives) and store copies off-server. Only your own tested backups guarantee you can recover.
What's a realistic uptime SLA for mid-range VPS hosting?
Reputable providers offer 99.9% uptime SLA, which allows about 43 minutes of downtime per month. Cheaper providers often have no SLA or don't compensate for outages. Read the actual SLA terms, not the marketing page.
How do I know if my VPS has enough disk IOPS for a database?
Run a quick fio test with random 4K writes. Database workloads need consistent IOPS under load. If you're seeing random write IOPS below 1000 or high latency spikes, your storage tier is too slow. Upgrade to local NVMe or a provider with guaranteed IOPS.
Is it worth moving SSH to a non-standard port?
Yes. It won't stop a determined attacker, but it eliminates 99% of automated bot traffic hitting your auth logs. Combined with key-only authentication and fail2ban, your SSH service becomes nearly invisible to opportunistic scans.
