VPNSmith
vps-hostingINFO

AWS to Contabo migration: 2026 cost optimization guide

Step-by-step migration of an EC2 + RDS + S3 stack to Contabo VPS + self-hosted Postgres + MinIO. Real savings, GDPR, downtime windows 2026.

By Eric Gerard · Founder · VPNSmith - Self-host VPN & GDPR VPS specialist11 min readPhoto: Luke Chesser - Unsplash

Your end-of-month AWS bill makes you grind your teeth. €187/mo for a Node.js + Postgres 40 GB + 30 GB of static objects stack, of which 60% goes to RDS and NAT Gateway. You know there's something cheaper, but you hesitate to abandon the comfort of EC2 and the magic of S3. This guide is the honest write-up of a migration we ran internally in April 2026: from AWS to a single Contabo VPS at €5.50/month, around 85% savings over 12 months, with no significant feature loss for our use case.

Why leave AWS in 2026

Three cumulative reasons converge in 2026 and make the migration conversation more mature than it has ever been.

The first reason is still raw cost. AWS scales brutally with egress traffic billed at $0.09/GB above 100 GB per month, NAT Gateways billed at $45/month just to exist before counting traffic, RDS snapshots that silently pile up at $0.095/GB-month with no default alarm, and managed services like Lambda whose per-invocation billing translates into unpredictable monthly bills. A project that starts at $30/month routinely ends up at $200-400/month in 18 months with no visible feature change. On our internal project described in this guide, the AWS bill had hit €187/month for a stack that could've run on a single €5.50/month VPS - an order of magnitude more expensive for an identical delivered service.

The second reason is legal sovereignty. Even in eu-central-1 (Frankfurt), AWS remains a US entity bound by the CLOUD Act, which means a US federal judge can compel access to data stored in Europe without the end user or client company being notified. For GDPR customer data, that's a legal risk formalized by EDPB recommendations from 2020 post-Schrems II. The first civil disputes based on this risk started emerging in 2024-2025 with the Mediawan / Microsoft Azure case which cost several millions in legal fees and emergency infrastructure redirection.

The third reason is technical lock-in. IAM, KMS, VPC, Application Load Balancer, Lambda - every AWS service ties you a bit more to the platform. After two years, "just moving" takes 3 weeks minimum of cumulative effort. The longer you wait to leave, the more expensive the migration becomes to project and therefore to do, which creates a procrastination loop where you keep paying rent to AWS without ever pulling the trigger. The psychological migration threshold is generally around month 6 or 12 of active use, after which the organizational inertia cost becomes prohibitive.

Beyond these three structuring factors, three operational triggers push an organization to concrete migration: a change of CIO or CTO that brings fresh perspective on the cloud bill; a GDPR or compliance audit that points to using AWS US as non-compliant with internal sovereignty policy; or a major AWS technical incident (us-east-1 outage propagated worldwide as in December 2024) that reminds you that single-vendor dependency has a real opportunity cost.

Contabo isn't magic: it's a low-end German VPS provider that hands you an Ubuntu box and lets you do the rest. But for 80% of SMB and solo SaaS workloads, it's more than enough - and 5 to 10× cheaper.

When migration pays off (and when it doesn't)

Be honest with yourself. AWS → Contabo makes sense if:

  • You have one or two services to host (API + DB + objects), not a 30-container microservice architecture.
  • Your traffic is predictable (no 100× baseline spikes). Contabo has no auto-scaling.
  • You accept becoming the admin: apt, systemctl, ufw, manual backups.
  • Your data doesn't tolerate the CLOUD Act, or your AWS bill is past €100/mo.

Conversely, stay on AWS if:

  • You heavily use Lambda, Cognito, SageMaker, managed SQS. Migration cost > AWS cost.
  • You have a customer SLA requiring 99.99% (Contabo is 99.9%, i.e. ~8h downtime/year).
  • You handle tens of TB of egress and your sustained outbound traffic is high enough to hit Contabo's fair-use throttling (traffic is "unlimited" but subject to a fair-use policy).

Our case at VPNSmith: a single Node.js backend + Postgres + static objects. Every box checked. Decision made in an hour.

Audit current AWS cost (Cost Explorer method)

Before migrating, measure. Without a baseline, there's no ROI.

  1. Go to AWS Cost Explorer → ReportsCost & Usage Reports.
  2. Filter the last 3 months, monthly granularity, grouped by Service.
  3. Export as CSV. Open in a spreadsheet. You typically get:
AWS ServiceAvg monthly cost
EC2 (1× t3.medium)€32
RDS (db.t3.small Postgres)€38
S3 (30 GB + requests)€4
Data Transfer Out€18
NAT Gateway€41
CloudFront€18
Route 53 + misc€6
Total€157 / mo

Annualized: €1,884. Note the detail: on this profile, NAT Gateway + Data Transfer = €59/mo, or 38% of the bill just to push bytes in and out. That's the classic blind spot.

Set up the target Contabo VPS

For this stack, we pick a Cloud VPS 10 from Contabo: 4 vCPU, 8 GB RAM, 75 GB NVMe, unlimited traffic (fair-use policy). €5.50/mo on a 12-month commitment. If your database plus objects exceed ~60 GB, step up to a Cloud VPS 20 or 30 for the extra NVMe.

Provisioning:

# Once the VPS is delivered (Contabo email with IP + root password)
ssh root@YOUR_IP

# Minimal hardening
adduser ericg
usermod -aG sudo ericg
mkdir -p /home/ericg/.ssh
nano /home/ericg/.ssh/authorized_keys   # paste your SSH key
chmod 700 /home/ericg/.ssh && chmod 600 /home/ericg/.ssh/authorized_keys
chown -R ericg:ericg /home/ericg/.ssh

sed -i 's/^PermitRootLogin .*/PermitRootLogin no/' /etc/ssh/sshd_config
sed -i 's/^#PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config
systemctl restart ssh

apt update && apt upgrade -y
apt install -y ufw fail2ban
ufw default deny incoming
ufw default allow outgoing
ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw --force enable
systemctl enable --now fail2ban

Full hardening details (Lynis, Contabo snapshots, journald) are in the WireGuard self-host guide. Same foundations apply here.

Postgres RDS → self-hosted Postgres migration (pg_dump step by step)

Rows of servers in a data center
Rows of servers in a data center

This is the most critical piece. Battle-tested procedure:

Step 1 - Install Postgres 15 on Contabo

sudo apt install -y postgresql-15 postgresql-contrib-15
sudo systemctl enable --now postgresql

# Create app user and DB
sudo -u postgres psql <<EOF
CREATE USER appuser WITH PASSWORD 'PASTE_A_STRONG_PASSWORD';
CREATE DATABASE appdb OWNER appuser;
GRANT ALL PRIVILEGES ON DATABASE appdb TO appuser;
EOF

Enable SSL and allow remote connections only from your app (or local-only if Postgres runs on the same machine as the API - recommended):

sudo nano /etc/postgresql/15/main/postgresql.conf
# ssl = on
# listen_addresses = 'localhost'  (or '*' if app lives on another VPS)

sudo nano /etc/postgresql/15/main/pg_hba.conf
# Add: hostssl appdb appuser YOUR_APP_IP/32 scram-sha-256

sudo systemctl restart postgresql

Step 2 - Dump from RDS

From your workstation, with RDS access:

pg_dump \
  -h your-rds.eu-central-1.rds.amazonaws.com \
  -U masteruser \
  -d appdb \
  -Fc \
  -f appdb.dump

# Custom format (-Fc) = compressed + parallelizable on restore

For a 40 GB database, expect 10-20 min depending on RDS class and bandwidth.

Step 3 - Transfer and restore

scp appdb.dump ericg@YOUR_CONTABO_IP:/tmp/
ssh ericg@YOUR_CONTABO_IP

sudo -u postgres pg_restore \
  -d appdb \
  -j 4 \
  --no-owner \
  --role=appuser \
  /tmp/appdb.dump

# Verify
sudo -u postgres psql -d appdb -c "SELECT count(*) FROM users;"

Check integrity by comparing count(*) of large tables between RDS and Contabo. Difference = 0.

Step 4 - Automated backups post-migration

You replace RDS automated backups with a simple cron:

sudo nano /usr/local/bin/pg-backup.sh
#!/bin/bash
DATE=$(date +%Y%m%d-%H%M)
sudo -u postgres pg_dump -Fc appdb > /var/backups/postgres/appdb-$DATE.dump
find /var/backups/postgres -name "appdb-*.dump" -mtime +14 -delete
# Push to MinIO or external S3 for off-site
rclone copy /var/backups/postgres/appdb-$DATE.dump remote:backups/postgres/

Daily cron at 3 AM: 0 3 * * * /usr/local/bin/pg-backup.sh.

S3 → MinIO migration (rclone, aws-cli compatibility)

MinIO is an open-source, Go-based object store that's 100% S3 API compatible. Direct install:

wget https://dl.min.io/server/minio/release/linux-amd64/minio
chmod +x minio
sudo mv minio /usr/local/bin/

sudo mkdir -p /data/minio
sudo useradd -r minio-user -s /sbin/nologin
sudo chown minio-user:minio-user /data/minio

sudo nano /etc/default/minio
MINIO_VOLUMES="/data/minio"
MINIO_OPTS="--console-address :9001 --address :9000"
MINIO_ROOT_USER=admin
MINIO_ROOT_PASSWORD=PASTE_A_STRONG_32_CHAR_PASSWORD

systemd unit: grab the official .service (MinIO docs) and systemctl enable --now minio.

Migrate objects from S3 using rclone:

sudo apt install -y rclone

rclone config
# n) New remote → name: aws / s3 / AWS / paste access_key + secret_key
# n) New remote → name: minio / s3 / Other / endpoint http://localhost:9000 / paste admin + password

# Bucket-to-bucket
rclone copy aws:my-prod-bucket minio:my-prod-bucket --transfers=8 --progress

For 30 GB: budget 30-60 min depending on AWS egress bandwidth (which will cost you a few euros in final transfer-out - that's the exit toll).

On the application side, no code change: your aws-sdk-js keeps working, you just point at the MinIO endpoint:

const s3 = new S3Client({
  endpoint: 'https://storage.yourdomain.com',
  region: 'us-east-1',           // arbitrary required value
  credentials: { accessKeyId, secretAccessKey },
  forcePathStyle: true,          // important for MinIO
});

Zero-downtime DNS cutover

The clean method, planned over 10 days:

  • D-10: deploy the full stack on Contabo, run internal smoke-tests via /etc/hosts override.
  • D-7: lower the TTL of A records in Route 53 from 3600 → 60 seconds. Let it propagate 48h.
  • D-3: feature freeze, last incremental pg_dump, last rclone sync of objects.
  • D-1: cut over at off-peak time (typically 3 AM UTC for an EU audience). Change the A record: old AWS IP → new Contabo IP. Propagation max 60s.
  • D+0 → D+2: aggressive monitoring (latency, 5xx errors, DB metrics). Keep AWS running "just in case".
  • D+7: clean up AWS (terminate EC2, delete RDS after final snapshot exported, delete S3 bucket after off-site backup).

Zero perceptible user downtime if Postgres is sync'd (a 5 min read-only freeze is enough to ship the final delta).

Want a Contabo VPS to kick off your migration? Contabo Cloud VPS 10, 12-month term - €5.50/mo

ROI estimate (before/after cost table over 12 months)

A representative before/after comparison based on each provider's published pricing:

Line itemAWS (before)Contabo (after)
Compute (EC2 t3.medium / Cloud VPS 10)€32€5.50
Database (RDS / self-hosted Postgres)€38€0 (included)
Object storage (S3 30 GB / MinIO)€4€0 (included)
Data transfer out€18€0 (unlimited, fair-use)
NAT Gateway€41€0 (not needed)
CloudFront CDN€18€12 (external BunnyCDN)
DNS Route 53€6€0.40 (free Cloudflare + 1 domain)
Off-site backup (Wasabi 30 GB)€0€2
Monitoring (UptimeRobot pro)€0€4
Monthly total€157€23.90
Annual cost€1,884€286.80

Saving: €1,597.20/yr, or about 85% on this representative profile. The exact figure depends on your stack, but for a comparable small-to-mid workload, savings in the 75-85% range are typical. Payback is fast: no significant migration cost (about a day of work).

What you lose vs AWS (managed services)

No marketing, let's be clear about the losses:

  • RDS Multi-AZ auto-failover: on AWS, if the primary dies, the secondary takes over in 60-120s. Self-hosted on Contabo, you'd need a second VPS + streaming replication + Patroni. Doable but adds ops time.
  • S3's 11 nines of durability: Amazon guarantees 99.999999999% durability per object (3-AZ internal replication). MinIO on a single disk = the durability of your NVMe disk. Fix: regular backups to Wasabi or Backblaze B2 (€1-3/mo for this dataset off-site).
  • Fine-grained IAM: replaced by Linux users + sudoers + MinIO policies. Less granular, simpler to manage.
  • Unified CloudWatch: replace with Prometheus + Grafana, or Netdata (15 min setup), or an external SaaS (Better Stack, Sentry).
  • Enterprise 24/7 support: Contabo offers email support, not the 24/7 enterprise tier AWS sells. For critical ops, plan a runbook + a second admin on call.

Budget 3 to 5 hours of ops per month in steady state: Ubuntu updates, backup checks, monitoring alerts. That's the real hidden cost - not insurmountable, but real.

Article published 2026-06-02. ROI estimate based on AWS and Contabo published pricing. Affiliate disclosure: if you pick up a Contabo VPS via the links in this article, we earn a commission at no extra cost to you. Our recommendations are based on published specs and pricing.

★ Nuremberg GDPR datacenter · ✓ Dedicated IPv4 included · 200+ Mbps guaranteed

Spin up the VPS from this guide → ContaboPublic IPv4 · full root · EU & US locations

Frequently asked questions

What's the concrete saving?
On our internal migration (Node.js stack + 20 GB Postgres + 30 GB objects): went from €187/mo AWS to €37/mo Contabo. Saving: ~80%, or about €1,800/yr.
What about latency vs AWS?
Comparable from Europe (Contabo DC Nuremberg vs AWS eu-central-1 Frankfurt = ~5ms gap). Bigger gap for US users, where AWS still wins.
What's the operational risk of leaving AWS?
Real but limited: no managed services (RDS auto-failover, S3 11 nines). You have to set up backup, monitoring, alerting yourself. Budget +3-5h/mo of ops.