Last updated 7 August 2026
There is no such thing as a typical Flask application, and that is the whole difficulty of writing this page. Flask is a microframework: it gives you routing, request handling and templates, and leaves the database, the migrations, the authentication, the background jobs and the file storage to you. Two projects with the same import line can have completely different hosting requirements.
So the useful way to read the table below is by what your application has grown. A stateless service that returns JSON fits the cheapest tier of any platform here. Add SQLAlchemy and you need a managed Postgres you are not personally responsible for. Add Celery and you need somewhere to run a process that is not a web server. Add uploads and you need object storage. Each of those moves the answer, and none of them is about Flask itself.
The one thing every deployment shares is that the development server is not a production server. Flask says so on startup, and it is the single most common way a first deployment goes wrong: one request at a time, no timeouts, a debugger that executes arbitrary code if debug mode survives into production. Every platform below expects you to bring gunicorn, uWSGI or waitress.
The short version: PythonAnywhere is the gentlest possible start, Render has the most usable free tier, Fly.io is the cheapest way to keep a small app online, and Granite — our own platform — makes sense once Flask has grown a database, a queue and somewhere to put uploads. If it is still one file and one route, we are the wrong answer and the table shows it.
At a glance
| Provider | From /mo | Free tier | Managed DB | Persistent disk | Deploy from |
|---|---|---|---|---|---|
| Fly.io | ~$2 | Postgres (unmanaged app) | Dockerfile, buildpack | ||
| Railway | $5 | yes ($1 credits) | Git, Dockerfile, template | ||
| Render | $7 | yes (spins down) | Git, Dockerfile | ||
| Granite | $9 | from Advanced | Git, Docker image | ||
| PythonAnywhere | $10 | yes (limited) | MySQL | yes (5 GB) | Git pull, web UI |
| Koyeb | $29 | limited | Serverless Postgres | Git, Dockerfile | |
| Google Cloud Run | usage-based | yes (monthly allowance) | via Cloud SQL | no (use GCS) | Container image |
Entry prices as published by each provider on 7 August 2026, sorted cheapest first. Usage, bandwidth and databases are billed on top almost everywhere — treat this column as a starting point, not a monthly bill.
PaaS, serverless or a plain VPS?
A VPS is always cheaper per gigabyte, and for Flask the gap is narrower than for heavier frameworks simply because you need fewer gigabytes. What a platform sells is everything around gunicorn: TLS and its renewal, zero-downtime rollouts, log collection, and database backups someone else is responsible for restoring. If the app is a hobby and you enjoy the machine, a VPS is a perfectly honest answer.
Serverless fits Flask better than it fits Django, for the same reason Flask exists: there is less to import. A small app boots in about a second rather than several, which makes scale-to-zero tolerable for internal tools and bursty APIs. The catch is not the cold start but the assumptions a small app tends to carry — a SQLite file on disk, uploads in a folder, a scheduler thread — none of which survive a platform with no filesystem and no long-lived process.
A managed platform earns its place at a specific moment: when the application acquires its second process. A web server plus a Celery worker plus a beat scheduler is three things that must share code and secrets and deploy together, and doing that by hand is where evenings go.
One file, no database, or you have never deployed anything before
PythonAnywhere or a free tier
Live in an afternoon, with nothing to configure and nothing to pay.
PythonAnywhere · Render free
SQLAlchemy, migrations, uploads and probably a Celery worker
Managed platform
Web, worker and beat deploy together, beside a Postgres you do not operate.
Granite · Railway · Render
Stateless service, idle most of the day, no long-lived processes
Serverless
Free while idle, and Flask's short import graph keeps the cold start bearable.
Cloud Run · Koyeb
The options
Fly.io
- Best for
- The cheapest way to keep a small Flask app online, especially a stateless one.
- Pricing
- Pay as you go. The smallest shared-cpu-1x machine with 256 MB RAM works out at roughly $2.02/month, billed per second.
- Cheapest entry point in this table, and a modest Flask app genuinely fits a 256 MB machine — unlike Django, where the same tier is a squeeze.
- Takes your Dockerfile, so the Python version and the WSGI server are entirely yours to pin.
- Multi-region and per-second billing are first-class.
- Postgres is a Fly app you operate and back up yourself, which is a real commitment the moment the app stops being stateless.
- You manage more infrastructure — machines, volumes and networking are exposed concepts.
- No free tier for new organisations since October 2024.
Railway
- Best for
- Assembling Flask, Postgres and Redis quickly without deciding anything in advance.
- Pricing
- Hobby is $5/month including $5 of usage credits; Pro is $20/month per workspace including $20 of credits. A free plan gives $1 of monthly credits, and there is a 30-day trial.
- Detects a Python project and runs it without configuration.
- Databases and Redis sit alongside services in the same project, so Celery has a broker within reach.
- A free plan and a 30-day trial for evaluation.
- Usage-based billing on top of the base fee makes the monthly cost hard to predict.
- The Pro fee is charged per workspace, which adds up for small teams.
Render
- Best for
- A free home for a small Flask app, and a simple paid tier once it earns one.
- Pricing
- Free web services are available but spin down after 15 minutes without traffic. The cheapest paid instance, Starter, is $7/month for 0.5 vCPU and 512 MB RAM.
- A genuine free tier for web services, which suits Flask's usual scale better than most.
- Managed Postgres, background workers and cron jobs in one account, which covers Celery and beat.
- Straightforward fixed instance pricing after the free tier — no credits to reason about.
- Free services spin down after 15 minutes idle; a Flask cold start is a second or two rather than Django's several, but the first visitor still waits.
- Costs climb once you need more than one small instance.
Granite
- Best for
- A Flask application that has grown a database, a queue and file uploads, and wants them in one project.
- Pricing
- Hobby is $9/month and includes $15 of monthly usage credits. Advanced is $39/month with $50 of credits, Professional $149/month with $200. Every plan has unlimited workspace seats.
- Managed Postgres, MySQL and Valkey run in the same project over internal DNS — the database and the Celery broker without a connection string leaving the cluster.
- S3-compatible storage with a CDN is where uploads belong once the container filesystem stops being trustworthy, which is immediately.
- Web app, Celery worker and beat are three resources from one image, so they share code, secrets and deploys.
- Unlimited workspace seats on every plan, and flat pricing that does not move with traffic.
- No free tier — the cheapest way in is $9/month, which is hard to justify for a single-file app.
- Persistent volumes start on the Advanced plan.
- Nothing here is Python-specific: there is no hand-holding if this is your first deployment.
PythonAnywhere
- Best for
- A first deployment, a teaching project or a small internal tool, where simplicity beats control.
- Pricing
- A limited free Beginner account runs one web app with restricted outbound internet. The Developer plan is $10/month: one web app on a custom domain, 5 GB of storage and 5,000 CPU-seconds a day.
- Built around Python and WSGI specifically, which is exactly what Flask is — you edit a WSGI file and the site is live, with no Docker and no build pipeline.
- A free tier that serves a real Flask site on a subdomain, which is genuinely useful for coursework and demos.
- MySQL and scheduled tasks are included rather than assembled.
- You work inside their environment rather than your own container, so anything unusual in your stack may simply not be possible.
- Background processing is limited — Celery is awkward here, and scheduled tasks are the intended answer.
- The free tier restricts outbound internet access to an allowlist, which breaks apps that call third-party APIs.
Koyeb
- Best for
- Edge presence with scale-to-zero for an app that is idle most of the day.
- Pricing
- The Pro plan is $29/month; Scale is $299/month. Serverless Postgres has a small free allowance.
- Edge locations included rather than sold separately.
- Managed Postgres available without leaving the platform.
- The highest entry price of any managed option here, which is a strange fit for a framework people usually choose to keep things small.
- Scale-to-zero means the first visitor after an idle period pays for the interpreter to boot.
Google Cloud Run
- Best for
- A stateless Flask service with spiky traffic, for teams already in GCP.
- Pricing
- No monthly fee. You pay per request and per resource-second, with a monthly free allowance. Cloud SQL and networking are billed separately.
- Scales to zero, so an idle service is genuinely free — and Flask's small import graph makes the cold start shorter than Django's.
- Takes any container image, so a slim multi-stage build applies unchanged.
- Effectively unlimited scale ceiling.
- No persistent disk, so uploads and any SQLite file must move before you deploy at all.
- Postgres, secrets and networking are separate GCP products you assemble and bill separately.
- Every instance opens its own connection pool, so autoscaling multiplies your database connections.
What a Flask app actually needs from a host
- Bring a WSGI server
- flask run is a development server: single-threaded by default, no request timeouts, and a debugger that will execute code sent by anyone who reaches it. Production means gunicorn, uWSGI or waitress with an explicit worker count — and a platform that lets you set the start command rather than guessing one for you.
- A stable SECRET_KEY
- Flask signs session cookies with it. Generate it once, store it as an environment variable, and never let the application invent one at startup: a fresh key per deploy silently logs out every user, and a different key per replica logs them out at random. It is the most confusing bug in this list because the application looks completely healthy.
- The app factory and the entrypoint
- Most non-trivial Flask projects use a create_app factory, and the platform needs to be told how to reach it — wsgi:app, app:create_app() or a module you provide. Platforms that auto-detect Python often guess app.py and nothing else, so check that the start command is yours to write.
- Migrations as a release step
- flask db upgrade must run once per deploy, after the build and before the new version takes traffic. In the container start command every replica races to migrate the same schema at the same time. Look for a release command or pre-deploy hook and treat its absence as a real limitation.
- SQLite does not survive
- Flask tutorials reach for SQLite, and it is genuinely fine locally. On any container platform the filesystem is discarded on deploy and not shared between replicas, so the database quietly resets or diverges. Move to managed Postgres or MySQL before the first real user, not after.
- Uploads belong in a bucket
- The same problem in a different costume: files written to a local folder disappear on the next deploy and are invisible to a second instance. A persistent volume works for a single instance; S3-compatible storage works for any number and puts a CDN in front of them.
- Somewhere for Celery
- If there is a queue, you need a long-running worker process, usually a beat scheduler, and Redis or Valkey as a broker. A platform that only runs web services means renting something else for this — and a scheduler thread inside the web process is not a substitute once there are two replicas.
- Memory per worker, not per request
- Each gunicorn worker is a separate process holding the interpreter and your application, so memory tracks worker count rather than traffic. Flask's floor is meaningfully lower than Django's — there is less framework to load — which is why the smallest tiers stay realistic here for longer.
So which should you pick?
Your first ever deployment, or a teaching project. PythonAnywhere. It hides everything you are not ready for, and the free tier serves a real site on a real URL.
A small app that should cost nothing. Render's free tier, accepting the spin-down after fifteen idle minutes.
The cheapest way to keep something small always on. Fly.io, at roughly $2/month. Flask is one of the few frameworks where that headline price genuinely applies rather than being a footnote.
Flask that has grown a database, a queue and uploads. This is where we would argue for Granite. Postgres or MySQL and Valkey run in the same project with no public endpoint, S3-compatible storage with a CDN gives uploads a permanent home, and the web app, the Celery worker and beat are three resources from one image that deploy together. From $9/month with $15 of usage credits.
Comparing Python frameworks rather than platforms? The Django and FastAPI comparisons cover the same providers with different conclusions, and the app platform page covers workers and cron jobs in detail.
Hosting for other stacks
Six ways to run a Go binary, from a $2 machine to scale-to-zero — and why Go stays cheap longer.
Seven options weighed on the things Django actually needs: media storage, a real Postgres, Celery workers and enough memory for gunicorn.
Vercel and six alternatives, weighed on the things that actually break when you self-host: ISR across replicas, image optimization and build-time env vars.
Six platforms plus Kamal, weighed on what Rails really needs: a release phase for migrations, a job runner, Active Storage and enough memory for Puma.
Laravel Cloud and six alternatives, weighed on queue workers, the scheduler, writable storage and the caches you must rebuild on every deploy.
Six platforms weighed on what an ASGI service actually needs: worker processes, connections that stay open, and a database pool that does not multiply out of control.
Six platforms weighed on the things Symfony assumes: a warmed cache built at build time, Messenger workers that restart on deploy, and Doctrine migrations that run exactly once.
Seven platforms for a framework that renders on every request — weighed on streaming, adapters, and how far the loaders sit from the database.
Six platforms weighed on what the JVM actually asks for: memory it is allowed to use, a container that knows its own limits, and a start-up you can afford to repeat.
Six places to run a container image, compared on what actually bites: architecture mismatches, registry access, signal handling and the volume you assumed would still be there.
Five ways to serve HTML that is already written — and an honest note about which of them we are not the right answer for.