I priced thirteen hosting providers for the same small app. The spread was 14x.
I have a couple of side projects and a bad habit of moving them. Every time a free tier ends or an invoice looks wrong, I spend an evening on pricing pages, pick something, and then forget every number by the next time I need them.
So this time I wrote them down, for myself. Same app, thirteen providers, August 2026 list prices, and not the marketing headline price - the price of the whole thing, including the database, the cache, the cron worker, the object storage, the load balancer, and the egress. Those last two are where most of the surprises live.
The second question was the one I actually cared about: what if one of these things randomly works. Going from a few hundred users to ten times that costs wildly different money depending on where you started, and by the end that mattered to me more than the difference between $7 and $95 at the bottom.
The app I actually priced
Comparing a static site on one host with a Kubernetes cluster on another proves nothing, so I started from usage, not from instance sizes. This is a real shape I have shipped more than once: a small B2B-ish SaaS with a dashboard, some uploads, and email.
- 5,000 registered users, of whom ~800 are active on a given day
- ~24,000 sessions per month, roughly 7 minutes each
- per session: 12 page views and ~25 API calls
- an API response is ~8 KB of JSON → 600k API calls, 4.6 GB out
- a cold page load is 300 KB, a warm one 40 KB → 17.8 GB of app shell and assets
- each session renders ~30 images at 120 KB → 720k requests, 86 GB out
- users upload ~15 GB/month, so the bucket sits around 20 GB in year one
- the app runs ~1.8M Postgres queries/month against ~10 GB of data
- the worker runs ~40k jobs/month: thumbnails, transactional email, a nightly digest
Add it up and the month looks like this: ~1.6M HTTP requests, ~108 GB of egress, ~0.6 requests per second on average with peaks around 15. Nothing here is heavy. p95 stays under 200 ms on a single small container.
Note what dominates: images are 80% of the bytes and the JSON API, the thing everyone benchmarks, is 4%. That one ratio decides more of the invoice than the framework, the language, or the instance type.
That usage maps onto a stack I fixed for every provider:
- one always-on Node/Bun HTTP service, roughly 0.25 vCPU and 512 MB in steady state
- one background worker doing cron and a queue
- PostgreSQL, ~10 GB of data
- Redis or something Redis-shaped for sessions and rate limits
- 20 GB of object storage for user uploads
- ~100 GB of egress per month
Same app, same month, $7 to $95. Nothing about the app changed, only who I gave the card to.
Where each dollar goes
The total is the least interesting number. The composition tells you what will break when the app changes shape.
Three things fall out of that chart:
- The database is the single biggest line on most platforms. Fly ($38 for Managed Postgres), Sevalla ($34), GCP ($28) and Supabase are all paying mostly for Postgres. Compute is nearly free by comparison.
- The cache is a hyperscaler tax. A 1 GB Redis is $3 on Heroku, $4 on Railway, $12 on ElastiCache and $36 on Memorystore. Same GB, 12x the price. On GCP that one line is more than the app and the worker combined.
- On Hetzner the whole box is one bar. Postgres, Redis, storage and traffic all live on the €8.49 server, which is exactly why it looks unfair. The cost has not disappeared, it moved into your evenings.
The self-managed end: Hetzner plus Coolify
A Hetzner CX33 is 4 vCPU, 8 GB RAM, 80 GB NVMe and 20 TB of traffic for €8.49/month. Add automated backups at 20% and you are at roughly $12. On that box, Coolify gives you a Heroku-ish UI: git push to deploy, automatic Let's Encrypt, a catalogue of 280-plus one-click services, Postgres and Redis as containers, preview deploys per PR. Self-hosted it costs nothing; their cloud control plane is $5/month for two servers if you would rather not host the panel too.
Dokploy is the leaner alternative - Docker Swarm underneath, first-class Compose support, much younger project. Coolify is Apache 2.0, Dokploy is source-available with restrictions on reselling. For a small team I would still take Coolify, purely for the app catalogue and the fact it has been around since 2022.
The catch is honest and boring: it is one box. You own the kernel updates, the disk filling up at 3am, and the restore drill. The 20 TB of included traffic is what makes the price look unfair though - on Render the same 100 GB overage would cost more than the whole Hetzner server.
Also worth knowing: Hetzner raised prices on 15 June 2026, and US locations cost about 20% more with 1 TB of traffic instead of 20 TB.
The PaaS middle
Railway came out best of the managed group at ~$26. Per-second billing at $0.0278/vCPU-hour and $0.0139/GB-hour, so an idle service actually costs close to nothing, and $5/month of the Hobby plan is credit you spend anyway. Config is a railway.json or the UI, templates cover the usual services, object storage is $0.015/GB-month with free egress. The thing I keep tripping on: their Postgres and Redis are just containers with a volume. You get backups, but you do not get a managed database in the sense that Render or Neon mean it.
Render is the polished one at ~$40 - web service $7, worker $7, Postgres Basic $19, Key Value $7. Everything is declared in render.yaml, previews per PR work properly, and it feels like Heroku did when Heroku was good. Two footguns: there is no object storage at all, so you are bolting on S3 or R2 anyway, and bandwidth over the included 100 GB per service is $30 per 100 GB. That is $0.30/GB, the most expensive egress in this entire comparison. With my 86 GB of images, I am one popular week away from that being the biggest line on the bill.
Fly.io is ~$53 and that is almost entirely Managed Postgres at $38/month plus $0.28/GB storage. The compute itself is cheap - a shared-1x machine with 1 GB is about $7 - and egress is $0.02/GB in NA/EU, which is excellent. If you run Postgres yourself on a second machine you land near $20, but then you are self-managing anyway and Hetzner does that cheaper. Fly wins when you genuinely need multi-region, which most small teams genuinely do not.
DigitalOcean App Platform is ~$50 and the most predictable pricing here: $10 for 1 vCPU/1 GB with 100 GiB transfer, $5 for the worker, $15 for managed Postgres, $15 for managed Valkey, $5 for Spaces. Nothing clever, nothing surprising, $0.02/GiB overage. It is the option you pick when someone else has to read the invoice.
Heroku is ~$27 and I was mildly surprised - Basic dynos at $7, Postgres Essential-1 at $9, Key-Value Mini at $3, and bandwidth is not metered at all. The floor is fine now. The ceiling is not: the next Postgres tier up is $50, dynos jump to $25, the filesystem is still ephemeral, and a request still dies at 30 seconds. Cheap to start, punitive to grow.
Sevalla was the most expensive of the PaaS group at ~$62, which is a shame because the product is nice. The app pods are reasonable ($10 for 0.5 CPU / 1 GB), but the database ladder goes $5 for 0.25 CPU / 1 GB of storage and then straight to $34 for the next size. There is no middle. Egress is $0.10/GB.
The hyperscalers
I added AWS and GCP mostly to check a suspicion: that for an app this size they are not just more expensive, they are more expensive in a way you cannot see on the pricing page.
AWS at ~$63 is two Fargate tasks (0.25 vCPU / 0.5 GB each, $0.04048/vCPU-hour and $0.004445/GB-hour, so ~$9 per task), RDS db.t4g.micro at ~$11.7 plus $2.3 of gp3 storage, an ElastiCache cache.t4g.micro at ~$11.7, and $1 of S3. Egress is genuinely $0 - AWS gives 100 GB/month free, and my app needs 108. Then the line nobody quotes: the Application Load Balancer is $16-18/month before a single request, which is more than the app and worker combined. Put your tasks in private subnets like the well-architected docs tell you to and a NAT Gateway adds another $33 plus $0.045/GB processed. The compute is cheap; the plumbing is not.
GCP at ~$95 is the most expensive line on the chart and it is almost entirely one service. Cloud Run is fine - the August 2026 rate is $0.000018/vCPU-second and $0.000002/GiB-second, so an always-on small instance is around $19 and the worker is $5, load balancing included. Cloud SQL for a db-g1-small with 10 GB is ~$28. Then Memorystore Basic is $0.049/GiB-hour, so the smallest 1 GB Redis is $36/month - more than the database. Egress is $0.12/GB on the Premium tier, so my 100 GB adds ~$11. Run Redis in a container on a e2-micro instead and GCP drops to ~$60, which tells you the problem is the managed cache, not the platform.
Neither number is an argument against AWS or GCP. They are an argument against using them for an app this size: you pay a fixed floor for infrastructure you do not need yet, and you buy IAM, VPCs and CloudFormation along with it. What you get is the only ceiling in this list that is effectively infinite.
The three outliers
Cloudflare Workers at ~$7 is the cheapest number on the chart and the least comparable. $5/month, 10M requests, 30M CPU-milliseconds, cron triggers for free, D1 for SQL, KV, R2 with zero egress fees. My 1.6M requests and 108 GB do not even register. If your app fits Workers, nothing else comes close on price. But "fits" is doing heavy lifting: D1 is SQLite not Postgres, Node compat is partial, there are no long-running processes, and rewriting a Postgres app to fit is not a hosting decision, it is an architecture decision.
Firebase at ~$22 surprised me on this workload. On Blaze: Firestore is $0.06 per 100k reads, $0.18 per 100k writes and $0.18/GiB stored, so 1.8M reads and 10 GB of data land around $6. Cloud Functions absorbs 640k invocations mostly inside the free tier, ~$2. The bill is 60% egress: Firebase Hosting and Storage both charge $0.15/GB after a small free quota, and 86 GB of images is $13. Put Cloudflare in front of the images and Firebase becomes the cheapest managed option here. Leave it as-is and it is the provider most exposed to a single viral thread - and Firestore reads are billed per document, so an N+1 in a list view costs real money rather than a slow page.
Vercel plus Neon plus Upstash at ~$45 is the default for a lot of people and it is fine, as long as you know what you are paying for. $20 for Pro, ~$19 for a Neon compute that is always on at $0.106/CU-hour, ~$5 for Upstash. You get the best deploy experience in the industry, previews that non-technical people can actually use, 1 TB of bandwidth included and $0.15/GB after. You do not get a place to run a worker that lives longer than a function invocation, which is exactly the thing my reference app needs.
Supabase at ~$32 sits in between: $25 Pro includes $10 of compute, an 8 GB Postgres, Auth, Storage, Edge Functions and pg_cron, and 250 GB of egress. Add ~$7 somewhere for the Node process and you are done, and you can often drop Redis entirely by using Postgres for queues and rate limits. Cheapest way to get a real managed Postgres with batteries attached.
The vertical axis is how little you touch a server, the bubble size is how annoying the migration out would be. There is no free lunch on that chart: everything cheap is either something you administer yourself or something you have rewritten your app for, and the two hyperscalers manage to be both expensive and hands-on.
Where the money actually leaks
Compute prices are within a factor of three of each other. Egress is not.
Hetzner includes 20 TB. Cloudflare R2 charges zero by design. Heroku does not meter bandwidth at all. Render charges $0.30/GB. That is a 15x spread on the one line that scales directly with how popular you get.
Since 80% of my bytes are images, I re-ran the whole bill with everything else held constant and only the egress growing - one bad Hacker News day, one customer who exports everything, one video feature:
At 100 GB the ordering is the one everyone quotes. At 2 TB it is a different post: Render goes from $40 to $610, Firebase from $22 to $307, AWS from $63 to $234, while Hetzner, Cloudflare and Heroku have not moved at all. Vercel's line is flat until exactly 1 TB and then bends, because that is where Pro's included bandwidth stops.
The practical version of this chart: put a CDN with free or cheap egress in front of your bytes and most of these lines flatten. That is one afternoon of work and it is worth more than picking the right host.
What if the thing actually grows
This is the part I care about more than the $7. A side project that works stops being a side project, and the question becomes how much the same architecture costs at ten times the load: 8,000 daily actives, 16M requests, 1 TB of egress.
- the app on 4 vCPU / 8 GB, split over two instances
- the worker on 1 vCPU / 2 GB
- Postgres on 4 vCPU / 16 GB with 100 GB of data
- 4 GB of Redis
- 200 GB of object storage
- 1 TB of egress
The absolute numbers are estimates. The slopes are the point:
Ten times the traffic is 4x the money on Hetzner and 18x on Render, and the two were $28 apart when I started.
Where the extra money goes is different in each case:
- Hetzner goes from one
CX33to twoCX43boxes (8 vCPU / 16 GB, €15.99 each), one for the app and one for the data. Traffic is still included, so 1 TB of egress costs nothing. You pay in work instead: Postgres replication, a load balancer, and the failover plan are yours. - Railway bills memory at ~$10 per GB-month, and at this size you are holding 25-30 GB of RAM. That single line is over half the bill. Compute is per-second and genuinely cheap; RAM is not.
- Render is the worst slope in the group, and almost all of it is egress: at $0.30/GB, the 900 GB over the included quota costs more than every instance on the account combined.
- Vercel stays sane on bandwidth (Pro includes 1 TB) and gets expensive on the database instead - an always-on 4 CU Neon compute is ~$310/month on its own.
- Supabase scales by compute add-on, so it is one clean line item: XL is $210/month for 4 cores and 16 GB. Predictable, but vertical only until you add read replicas, because there is still one writer.
- Firebase has the widest error bar of anything here. Storage and functions scale linearly and politely; Firestore reads do not, because they scale with how your UI queries rather than with your traffic. My ~$280 assumes the same access pattern at 10x. A live listener on a growing collection can double that without any more users.
- AWS at ~$640 is the fixed floor finally paying off - the ALB and NAT that cost more than the app at $63 are rounding errors at 10x, and Fargate plus RDS just scale. This is the size where AWS stops looking silly.
- GCP lands near AWS at ~$660, with Cloud SQL at ~$217 and a 4 GB Memorystore at ~$143 doing most of the damage. Cloud Run itself handles the traffic without you doing anything.
- Cloudflare barely moves. 100M requests a month is $5 plus $0.30 per extra million, and R2 still charges nothing for egress. If the app fits Workers, it is the only option here that does not care whether you have 500 users or 500,000.
Vertical, horizontal, and what actually blocks you
| Scale up | Scale out | What hurts first | |
|---|---|---|---|
| Hetzner + Coolify | resize the server, one reboot | add servers, wire a load balancer yourself | Postgres HA is entirely your problem |
| Railway | sliders, per-second billing | replicas per service | memory pricing, and the DB is a container |
| Render | change instance type | autoscaling on paid plans | egress at $0.30/GB |
| Fly.io | bigger machines | fly scale count, real multi-region | managed Postgres tiers |
| DigitalOcean | bigger instance | autoscaling on Professional | database tier jumps |
| Heroku | bigger dynos | ps:scale, instant | dyno and Postgres tier prices, 30s request cap |
| Supabase | compute add-on | read replicas only, one writer | write throughput on a single Postgres |
| Firebase | nothing to do | automatic | read amplification, and query shapes Firestore cannot do |
| Vercel | nothing to do | automatic | function invocations plus the external database |
| Cloudflare | nothing to do | automatic, globally | your architecture, not the bill |
| AWS | change task and instance size | ASG, ECS service autoscaling, read replicas | your own YAML, and the bill's fixed floor |
| GCP | change instance size | Cloud Run autoscales, Cloud SQL replicas | Memorystore pricing, single-writer Cloud SQL |
The honest summary: vertical scaling is cheap everywhere and horizontal scaling is where the platform earns its markup. On a VPS you can double the box in a reboot for €8 more, but going from one box to three with a replicated database is a weekend and a runbook. On Railway or Render it is a number in a form, and you pay 5-10x per unit of compute for that. That premium is fine while the app is small; it is what people mean when they say a platform "got expensive" at scale.
The other thing worth planning for: the two cheapest options at 10x are the two with the least room to grow into. Hetzner is cheap because you are the ops team, and Cloudflare is cheap because you have already written your app to its shape. Neither gets cheaper by accident.
What you get without wiring it yourself
This is what actually matters for a small team - not raw price, but how many services you have to glue together on a Sunday.
| Postgres | Redis / KV | Cron | Object storage | PR previews | |
|---|---|---|---|---|---|
| Hetzner + Coolify | container | container | container | no, add R2 | yes |
| Railway | container | container | yes | yes | yes |
| Render | managed | managed | yes | no | yes |
| Fly.io | managed | no | yes | no, add Tigris | no |
| DigitalOcean | managed | managed | preview | Spaces | yes |
| Heroku | managed | managed | add-on | no | yes |
| Sevalla | managed | managed | yes | yes | yes |
| Supabase | managed | no | pg_cron | yes | branches |
| Firebase | no, Firestore | no | Scheduler | yes | channels |
| Vercel | no | no | yes | Blob | yes |
| Cloudflare | D1 only | KV | yes | R2 | yes |
| AWS | RDS | ElastiCache | EventBridge | S3 | no, build it |
| GCP | Cloud SQL | Memorystore | Scheduler | GCS | no, build it |
Thirteen lines on one radar is unreadable, so here they are in the three groups they actually compete in. The scoring is mine, not a benchmark, so argue with it - the shape is the point.
Roll your own and classic PaaS. Hetzner wins on cost and portability and loses on setup; the others trade a bit of each for a UI.
Serverless and hyperscalers. The two shapes are mirror images: Vercel and Cloudflare are instant and rigid, AWS and GCP are configurable and slow to stand up. All four have the scale headroom.
Batteries included. Supabase and Firebase buy you the most managed surface per dollar and cost you the most portability - Supabase is still Postgres you can pg_dump, Firestore is not.
So what would I actually pick
- Side project, weekend, might die in a month: Cloudflare Workers if it fits, otherwise Railway. Both cost near zero when idle.
- Real product, small team, you want to stop thinking about it: Supabase for the data layer plus one small compute box. Best ratio of managed features to dollars in this list.
- Client work where the bill has to be defensible: DigitalOcean App Platform. Boring, predictable, nobody gets a surprise.
- You are cost-sensitive and not scared of a terminal: Hetzner plus Coolify, and set up the restore drill on day one, not after the first incident.
- Next.js-shaped frontend with a separate API: Vercel for the frontend only, anything else for the backend. Paying Vercel prices for a background worker is how the $45 becomes $200.
- Mobile app, small team, no backend engineer: Firebase, with a CDN in front of the images and a hard look at your read patterns before launch.
- You already have an AWS or GCP org, or compliance says so: use it, and accept that the first $60 buys you plumbing rather than product. Below a few thousand users it is the wrong tool; above that it stops mattering.
- It might actually grow and you do not know yet: start managed, but keep the app in a Dockerfile and the data in plain Postgres with no proprietary extensions. That one rule is what makes the move to a box you own a boring afternoon instead of a rewrite, and at 10x it is the difference between $50 and $500.
The thing I would not do is pick a provider because it was cheap at the tier I am on today. Every platform here is affordable at the bottom; what differs is the slope. Hetzner and Cloudflare barely move, Supabase and DigitalOcean roughly track the load, AWS and GCP start high and stay flat-ish, and Render, Heroku and Railway multiply faster than the traffic does - Render because of egress, the other two because of memory pricing and tier jumps.
Prices are August 2026 list prices, no promos, no annual discounts, no reserved instances, no VAT, EU regions where the provider has them. The usage model is a real app's shape, but both scenarios are my own estimates built from published rate cards, not measured invoices - the 10x numbers especially, since they assume steady utilisation and nobody's traffic is steady. Argue with the numbers, the ranking and the slopes are what I would stand behind.