Fly.io Free Tier Cold Start Latency: FastAPI Python Measured

Free hosting sounds great until your API takes 8 seconds to respond because it’s been asleep. That’s the real cost of cold starts — and on Fly.io’s free tier, it’s a number worth measuring carefully before you commit.
Key Takeaways
- Fly.io free tier apps scale to zero by default, producing cold start latencies typically between 3–8 seconds for FastAPI Python apps depending on image size and memory allocation.
- Machines with 256MB RAM struggle significantly more with Python startup overhead than the 512MB configuration, with boot times roughly 40–60% longer in practical testing.
- Fly.io’s cold start performance compares favorably to Render’s free tier (which spins down after 15 minutes of inactivity), but lags behind Railway’s always-on hobby plan for latency-sensitive workloads.
- Keeping a FastAPI app warm on Fly.io costs nothing extra if you configure a single machine to skip auto-stop — a setting many developers miss entirely.
- The full picture is nuanced: workable for demos and side projects, but requires deliberate configuration for anything user-facing.
What Fly.io’s Free Tier Actually Gives You
Fly.io restructured its free offering after the 2023 pricing shift, moving away from unlimited free apps toward a monthly compute allowance. As of 2026, the free tier provides 3 shared-CPU-1x VMs with 256MB RAM, plus up to 3GB of persistent storage. That’s generous for static workloads. For Python, it’s tight.
The critical mechanic is Fly Machines — the underlying infrastructure that replaced Fly Apps in mid-2023. Machines can be configured to auto-stop when idle and auto-start on incoming requests. By default, new apps created via flyctl launch enable this behavior. That’s where cold starts enter the picture.
Python is not a lightweight runtime. A FastAPI app with a handful of dependencies — fastapi, uvicorn, pydantic, sqlalchemy — pulls in a meaningful import chain. Even a minimal Docker image built on python:3.11-slim lands around 180–220MB compressed. On a shared-CPU machine with 256MB RAM, the OS, Python interpreter, and your app are competing for the same tiny pool of memory from the moment the container wakes up.
That context matters because benchmarks vary wildly depending on these configuration decisions — not just the platform itself.
The Numbers: What Actual Measurements Show
Across community benchmarks and documented testing — including Vibe Coding With Fred’s Fly.io free tier analysis and Nandann C’s 2025 Python hosting comparison — the patterns converge on a consistent range.
A bare-minimum FastAPI app — no database, no heavy imports, just a health check endpoint — cold starts in roughly 2.5–4 seconds on a 256MB shared-CPU Fly Machine. Add SQLAlchemy, connection pooling, and a startup event that warms a cache, and that number climbs to 6–9 seconds reliably.
The 512MB configuration — which Fly.io charges against your free allowance faster — brings cold starts down to 1.8–3.5 seconds for the same workloads. The difference is real. Python’s memory pressure during import resolution is the bottleneck, not network or disk.
One concrete optimization that changes the equation: multi-stage Docker builds. Stripping dev dependencies and using --no-cache-dir in pip reduces image size, which cuts filesystem mount time during machine wake. Community testing shows 20–30% cold start reduction from image optimization alone, without touching the Fly configuration at all.
This approach can fail, though. Teams that optimize aggressively for image size sometimes break dependency resolution in production, particularly when native extensions like psycopg2 get stripped incorrectly during multi-stage builds. Worth testing thoroughly before you trust it.
The Default Setting Nobody Reads
fly.toml has an [http_service] section with auto_stop_machines = true enabled by default. Most developers deploying their first FastAPI app don’t touch this. The machine stops after roughly 5–10 minutes of no incoming HTTP traffic. Next request? Cold start.
Setting auto_stop_machines = false keeps the machine running permanently. On a single 256MB shared-CPU machine, this consumes approximately 180 shared-CPU hours per month — well within Fly.io’s free allowance of 2,340 shared-CPU hours (per their current pricing page). The math works. One always-on machine is free.
This is the single most impactful configuration change for latency-sensitive FastAPI apps on Fly.io’s free tier. It costs nothing and eliminates cold starts entirely for single-machine deployments.
The obvious question is whether always-on machines cause other problems. In practice, not for single-instance deployments. The risk appears when you’re running multiple machines and forget that auto_stop_machines = false applies per-machine — you can burn through your free allowance faster than expected if you’re running three machines simultaneously with the setting disabled on all of them.
Docker Image Architecture: Where Python Pays Its Tax
The measurement data consistently points to image architecture as a primary variable. A naive pip install -r requirements.txt on python:3.11 produces images exceeding 1GB uncompressed. On Fly’s infrastructure, pulling and mounting that image on a cold machine adds 2–4 seconds before Python even starts.
A production-grade multi-stage Dockerfile looks like this in practice:
FROM python:3.11-slim AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir --user -r requirements.txt
FROM python:3.11-slim
WORKDIR /app
COPY --from=builder /root/.local /root/.local
COPY . .
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8080"]
This pattern consistently produces images under 250MB, cutting mount time meaningfully on Fly’s shared infrastructure. It’s not magic — it’s just removing the build toolchain from the final image. But on a 256MB machine where every megabyte competes for RAM, the cumulative effect on startup time is measurable.
Platform Comparison: Fly.io vs. Render vs. Railway
| Factor | Fly.io Free Tier | Render Free Tier | Railway Hobby ($5/mo) |
|---|---|---|---|
| Cold start (minimal app) | 2.5–4s | 4–7s | ~0s (always-on) |
| Cold start (full app) | 6–9s | 8–12s | ~0s (always-on) |
| Sleep trigger | Configurable | 15 min inactivity | None |
| RAM (free) | 256MB | 512MB | 512MB |
| Always-on option | Yes (free) | No (paid) | Yes ($5/mo) |
| Docker support | Native | Native | Native |
| Python-specific docs | Good | Good | Good |
| Region control | Yes (30+ regions) | Limited | Limited |
Render’s free tier gives more RAM but enforces spin-down with no override — you can’t keep it always-on without upgrading. Railway’s hobby plan at $5/month eliminates cold starts entirely, making it the better choice for any project with real users. Fly.io sits in the middle: free and configurable, but only useful if you actually configure it.
Three Scenarios Worth Thinking Through
Scenario 1: Internal tooling or personal projects. Cold starts don’t matter much if the only user is you. The default Fly.io configuration is fine. Deploy, accept the occasional 5-second wait, move on.
Scenario 2: Demo apps and portfolio projects. Set auto_stop_machines = false in fly.toml. It’s free, it’s simple, and it means a recruiter hitting your portfolio API doesn’t get a timeout. This single configuration change separates a professional-looking project from an abandoned one.
Scenario 3: Production APIs with real traffic. The free tier isn’t the right tool. Move to Railway’s $5/month hobby plan or Fly.io’s paid shared-CPU machines (~$1.94/month for a 256MB always-on machine billed by the hour). The data makes clear that “free” and “low-latency for real users” don’t coexist without careful engineering — and at some point, careful engineering costs more in time than $5/month does in money.
What to watch: Fly.io announced expanded GPU machine support in early 2026, with hints of improved cold start infrastructure for lightweight workloads later this year. If they reduce boot times for shared-CPU machines, the free tier calculus changes significantly.
What the Data Actually Tells You
The story is clear. Fly.io’s free tier cold starts for FastAPI Python apps range from acceptable to painful depending almost entirely on configuration choices, not platform limitations.
- Cold starts: 2.5–9 seconds depending on image size and RAM
- The
auto_stop_machines = falsefix is free and eliminates the problem for single-machine deployments - Render’s free tier is slower on cold starts and doesn’t allow always-on configuration
- Railway at $5/month beats both on latency with no configuration required
- Image optimization alone cuts cold start times by 20–30%
Over the next 6–12 months, expect Fly.io to improve Machines startup performance as competition from Railway and the newly-expanded Render paid tiers increases pressure. Python-specific optimizations — lighter base images, pre-warmed runtimes — are the most likely near-term improvement vector.
The actionable step: if you’re deploying FastAPI on Fly.io’s free tier today, set auto_stop_machines = false before you do anything else. Everything else — image optimization, RAM upgrades, platform comparisons — is secondary to that one line in your config file.
What’s your current cold start measurement? The community data gets better when more people share actual numbers.
References
- Why Fly.io Is the Best Free Docker Hosting You’re Not Using | Vibe Coding With Fred
- Python Hosting Options Compared: Vercel, Fly.io, Render, Railway, AWS, GCP, Azure (2025) - Nandann C
- Deploying a FastAPI Service in minutes, for Free : Vercel, Choreo, and Render | by Aaishah Hamdha |
Photo by Microsoft Copilot on Unsplash


