What It Actually Costs to Run a SaaS on EU Infrastructure
The default choice
Most startups default to AWS. It is what you used at your last job, it is what every tutorial assumes, and nobody ever got questioned for choosing Amazon. We went with Hetzner instead.
SendRec’s entire production stack runs on a single Hetzner server in Helsinki. The monthly bill is about €6. It serves the live application, stores recordings, collects privacy-respecting analytics, terminates HTTPS, and runs automated daily backups.
What runs on the box
The server is a Hetzner CX33: 4 vCPUs, 8 GB RAM, 80 GB NVMe SSD. Everything is orchestrated with a single docker-compose.yml. Ten containers:
Caddy serves the static landing page, auto-provisions HTTPS certificates via Let’s Encrypt, and reverse proxies requests to all other services. No nginx config tuning, no certbot cron jobs, no separate load balancer.
SendRec app is the core product — a Go binary with an embedded React frontend. It handles user authentication, screen recording uploads, video sharing, and the watch page.
MinIO provides S3-compatible object storage for video recordings and thumbnails. It runs locally on the same server, so video data never leaves the machine unless a user shares a link.
Listmonk handles email. It is a self-hosted mailing list manager — open source, single binary, with a proper admin UI. It handles double opt-in, campaigns, and transactional email like password resets. It replaces Mailchimp.
Umami handles analytics. No cookies, no personal data collection, GDPR-compliant without a consent banner. It shows us pageviews, referrers, and countries — the things that actually matter. It replaces Google Analytics.
Five PostgreSQL instances back the app (production and staging), Listmonk, and Umami. All run the Alpine image and stay well within the 8 GB of available RAM.
Caddy doubles as the API gateway. All subdomains — app.sendrec.eu, storage.sendrec.eu, sendrec.eu — route through a single Caddy instance. From the visitor’s perspective, everything feels like one service. From the ops perspective, each container is isolated and independently upgradeable.
There is no Kubernetes and no Terraform. Deployments are handled by GitHub Actions — push to main deploys to staging, tag a release for production. Each deploy SSHs into the server and runs docker compose up -d --build.
What this costs on AWS
The fairest comparison is the same Docker Compose stack on a different provider. An EC2 t3.large (2 vCPU, 8 GB RAM) with 80 GB of gp3 storage costs around $61/month on-demand. Same containers, same Caddy config, same self-hosted services. Over 10x what we pay Hetzner for equivalent specs.
In practice, most teams on AWS do not stop at a bare EC2 instance. They add an Application Load Balancer ($16/month) because that is how you get AWS Certificate Manager. They use RDS instead of Postgres in Docker, S3 instead of MinIO, and managed email instead of Listmonk. A typical managed AWS setup doing the same job lands well over $100/month.
Our total: €6.04/month.
Both comparisons make the same point. Even the charitable one — identical Docker stack, different provider — is over 10x more expensive. And the cost difference is the least interesting part.
Why this is not just about cost
The cost difference is striking, but it is not the reason we chose Hetzner.
Hetzner is a German company — founded in 1997, headquartered in Gunzenhausen, operating data centers in Nuremberg, Falkenstein, and Helsinki. Our server runs in Helsinki. No American parent company, no US subsidiary, no CLOUD Act exposure. When we say user data stays in the EU, we mean it is on servers owned by a European company under European jurisdiction — not in an EU region of an American cloud provider. These are legally different statements.
The rest of the stack
The EU-first principle extends beyond the server:
DNS goes through Cloudflare in DNS-only mode. Cloudflare is a US company, but in DNS-only mode they resolve domain queries without ever proxying or inspecting our traffic. They never see user data.
Transactional email is handled by Brevo (formerly Sendinblue), a French company. They relay the opt-in confirmation emails that Listmonk sends. 300 emails per day on their free tier, which is more than enough at this stage.
Business email uses Cloudflare Email Routing to forward addresses like hello@sendrec.eu to a personal inbox. No mailbox hosting, no stored email data on third-party servers.
CDN — when we need video delivery, we plan to use BunnyCDN, a Slovenian company.
Backups run via a cron job at 3 AM UTC. A shell script dumps both PostgreSQL databases, compresses them with gzip, and keeps seven days of rolling backups on the server’s local disk. The entire backup script is 24 lines of bash.
Apart from Cloudflare resolving DNS, no US company touches user data at any point in this stack.
What we would tell other founders
If you are starting a SaaS, look at what you actually need before picking a cloud provider. At early stage, the answer is almost always: a VPS, Docker, and a reverse proxy. Hetzner, OVH, and Scaleway all offer this in the EU for single-digit euros per month.
The admin panel is less polished than the AWS console. There is no managed Kubernetes, no click-to-deploy, no marketplace of pre-built integrations. What you get is a fast server in a European data center, honest pricing, and no legal complications.
If your product handles EU user data, the infrastructure decision is also a legal decision. You can make it intentionally for €6/month, or you can make it by default for $61/month and still end up with CLOUD Act exposure.
What we are building
SendRec is an open-source async video messaging platform for EU teams. Record your screen, share a link, done — all data stays in the EU. The infrastructure, the code, and the architecture decisions are all public.
Try it free — 25 videos per month, no credit card required. Or self-host it from the source on GitHub.