Jako Heiberg
HomeInsightsMusingsPortfolioAboutContact
Jako Heiberg

From DBase III+ to edge computing.
The journey continues.

Pages

  • About
  • Portfolio
  • Resume / CV
  • Insights
  • Musings
  • Archive
  • Contact

© 2026 Jako Heiberg · Cape Town, South Africa · UTC+2

Built with React + Cloudflare Workers. No PHP was harmed.

Back to Insights
Insights

FastAPI vs Flask: I've Used Both, Here's What They Don't Tell You

Flask will do exactly what you tell it to and nothing more, which sounds like a compliment until you realise how much you forgot to tell it. FastAPI has opinions, and after shipping production APIs with both, I've come around to thinking that's the point.

May 7, 2026
5 min read
TechnologyPython

Flask has been around since 2010, which in Python framework years makes it practically ancient. It pioneered the micro-framework philosophy: give you routing, a request/response cycle, and a dev server, then get out of your way. The ecosystem filled in the rest. Marshmallow for serialization. Flask-Login for auth. Flask-SQLAlchemy for the database. A dozen more packages depending on what you are building.

For most of the 2010s, this was exactly right. Developers wanted control. They wanted to choose their own tools. Batteries included was almost a slur.

Then FastAPI arrived in 2018 and quietly changed what opinionated means.

What Flask Gets Right

Flask's simplicity is genuine, not superficial. A Flask app that serves JSON can fit in fifteen lines. The routing is readable. The request object is always there when you need it. Blueprints make it reasonable to structure larger apps without fighting the framework.

If you're building something small — an internal tool, a webhook receiver, a quick prototype — Flask is still excellent. It's stable, widely understood, and every developer on your team will already know it. Zero onboarding friction is worth something.

Flask also doesn't hide its internals. When something goes wrong, the stack trace is comprehensible. The source code is readable. This is more valuable than it sounds when you're debugging at midnight and Stack Overflow isn't giving you anything useful.

What Flask Silently Asks You to Build

Here's where I'll put on my opinionated hat and leave it there.

Flask trusts you to handle validation. This sounds fine until you've spent two hours tracking down a bug caused by a query parameter that was supposed to be an integer but arrived as a string, and Flask politely accepted it because that's what you told it to do. Nothing.

You're also responsible for your API documentation. You can add Flask-RESTX or Flasgger to generate Swagger docs, but now you're maintaining two sources of truth: your route handlers and your doc annotations. They drift. They always drift.

And async. Flask added async support in 2.0, but it's bolted on. The original design is synchronous, and that lineage shows. You can use async def on routes, but you're still running on a synchronous WSGI server by default, which means you're not actually getting concurrent I/O unless you switch to an ASGI server and reconfigure things. It works, but the seams are visible.

What FastAPI Actually Does

FastAPI is built on Pydantic and Starlette from the ground up. This sounds like an implementation detail but it's actually the whole game.

When you define a FastAPI route, your function's type annotations are the validation logic. You're not writing a schema separately from your handler — you're writing the handler, and the schema emerges from it. If you say a parameter is an int, FastAPI validates it, coerces it, and surfaces a clean error response if it fails. If you say the request body is a UserCreate Pydantic model, FastAPI validates every field, handles nested objects, runs custom validators, and rejects malformed payloads before your code ever runs.

This is the thing that sounds like a minor convenience until you've actually shipped it. You stop writing defensive code at the top of every handler. You stop writing check that this field exists, check that it is the right type, check that it is in the right range. That code just doesn't exist anymore.

The Swagger UI is generated automatically from your type annotations and shows up at /docs. It's always accurate because it's generated from the same code that runs the validation. There's no second source of truth to drift.

And async is native. FastAPI runs on ASGI with Starlette underneath, so async def means actual async I/O, not a compatibility wrapper. For endpoints that hit a database, an external API, or anything with latency, this matters.

The Honest Trade-off

FastAPI's learning curve is real if your team hasn't worked with Python type hints or Pydantic before. The first Pydantic model feels like paperwork. By the third one, you start wondering why you ever did it any other way.

The ecosystem is younger too. Flask's plugin ecosystem is extensive and battle-tested. FastAPI's is growing fast but you'll occasionally reach for something that doesn't exist yet and have to write it yourself. This happens less than it used to. It still happens.

There's also the Pydantic v1 to v2 migration, which anyone who went through it has opinions about. Pydantic v2 is faster and stricter, but the migration was not trivial. FastAPI's fate is tied to Pydantic's, which is mostly a good thing — Pydantic v2 is excellent — but worth knowing.

What I'd Choose Today

For anything new that needs to be production-ready — which in 2025 means validation, documentation, async support, and type safety — I'd choose FastAPI without much deliberation. The boilerplate it eliminates isn't incidental; it's the boilerplate that hides bugs.

For a quick script that needs to expose two endpoints, Flask is still fine. It'll be done in ten minutes and it'll work.

The framing of FastAPI vs Flask implies a competition, but it's really a question of what layer you want to work at. Flask gives you the primitives. FastAPI gives you the patterns. If your project is large enough to need the patterns — and most production APIs are — FastAPI will save you more time than it costs.

Jako Heiberg

Software developer with 40+ years of building things that work. Full-stack, FastAPI, React. Based in Cape Town, working remotely, worldwide.

Related Posts

Insights

Vim From Scratch — Part 2: Modal Editing, and Why Modes Are a Feature

Every other editor lets you type text the moment you open it. Vim makes you ask for permission first. This sounds insane until you realise it's the reason Vim can do so much with so few keys.

August 26, 2026
5 min read
Insights

The Long Game: Staying Employable Without Burning Out

A software career is a forty-year marathon disguised as a series of sprints. Here is how to keep learning without chasing every shiny thing, and keep going without burning to the ground.

August 19, 2026
6 min read
Insights

Your First Job: What Nobody Warns You About

You got in. Now everyone else seems to know things you do not, the real codebase is a horror, and you are convinced they will realise they made a mistake hiring you. Good news: all of that is completely normal.

August 12, 2026
6 min read