# What Is FastAPI? Python's Type-Hint-Driven API Framework

> FastAPI is a high-performance Python framework using Pydantic and Starlette to deliver automatic validation, documentation, and Go-level throughput.

Source: https://camnangai.com/en/engineering/what-is-fastapi  
Published: 2026-08-10

**FastAPI** is a modern, high-performance web framework for building APIs with
  [Python](https://camnangai.com/en/engineering/what-is-python), powered by Starlette and Pydantic.

It uses standard Python type hints to automate data validation, serialization, and documentation,
and one annotation buys all three.

The pitch is narrow, and it holds up: you write ordinary Python type hints instead of the
boilerplate older frameworks make you write by hand, and throughput stays on par with
[Node.js](https://camnangai.com/en/engineering/what-is-nodejs) and Go.


  It is built for production environments that demand high concurrency, type safety, and efficient
  resource management.


![One Python type annotation in FastAPI buys three things at once: data validation, auto-generated API documentation, and high throughput](https://camnangai.com/articles/fastapi-la-gi/01-infographic-en.webp)

## What is FastAPI?

**FastAPI** is a microframework based on standard Python type hints, and current releases require
Python 3.10 or newer. It was engineered to solve the chronic lack of automatic validation and
high-performance asynchronous support in older tools like Flask and Django. Architecturally, it is
the spiritual successor to APIStar. Its reliability is rooted in technical continuity: the framework
is built on Starlette and Uvicorn, both created by Tom Christie, the architect behind Django REST
Framework.

Adoption reaches well past small services. Microsoft uses FastAPI for machine learning
services integrated into Windows and Office. Uber uses it for its Ludwig platform, and Netflix
employs it for Dispatch, its crisis management orchestration framework. Cisco has integrated the
framework into its API-first strategy to power services like its Virtual TAC Engineer. That list is
not proof FastAPI is the best framework available; it is proof that nobody has to defend the choice
in a design review.

The project's own numbers are worth stating with their caveat attached. FastAPI's documentation
claims the framework increases feature development speed by 200% to 300% and reduces
developer-induced errors by about 40%, though its own footnote attributes those figures to tests
run by an internal development team, not to independent measurement. Treat them as the
maintainers' estimate rather than a benchmark.

## What does a FastAPI endpoint look like?

The mechanics of a **FastAPI** application involve instantiating the `FastAPI` class and using
decorators that match [HTTP](https://camnangai.com/en/engineering/what-is-http) methods, such as `@app.get()` or
`@app.post()`. This routing system is intentionally designed to mimic the API design of the Requests
library, making it immediately accessible to anyone familiar with the Python ecosystem.

FastAPI handles data extraction through function parameters. Path parameters are defined within the
decorator's string, while any arguments not present in the path are automatically interpreted as
query parameters.

```python
from fastapi import FastAPI

app = FastAPI()

@app.get("/items/{item_id}")
def read_item(item_id: int, q: str | None = None):
    return {"item_id": item_id, "q": q}
```

By declaring a parameter's type once, you gain validation, serialization, and IDE autocompletion
simultaneously. Pass a string where `item_id` expects an `int` and the framework returns a 422
Unprocessable Entity with the exact location of the fault, before your function body ever runs. This
design minimizes duplication and keeps the code as the single source of truth for the API contract.
The function signature is the spec, so there is no second copy of it to keep in sync.

## Type hints and Pydantic: validation and automatic docs

FastAPI uses Pydantic to enforce data types across your API, supporting everything from basic
integers to complex nested JSON structures, UUIDs, and URLs. Because it relies on standard Python
types, there is no new domain-specific language to learn. Pydantic V2 rewrote the validation core in
Rust, so that enforcement is considerably cheaper than it used to be.

The framework natively generates OpenAPI and JSON Schema specifications, which is what enables the
automatic interactive documentation. By default you get two UIs: **Swagger UI** at `/docs` for
browser-based testing, and **ReDoc** at `/redoc` for a clean rendering of the specification. Any
change to a Pydantic model is reflected immediately in both, so the documentation cannot drift from
the code.

There is a cost worth accounting for. While Pydantic is the right tool for validating data at API
boundaries, using Pydantic models for every internal data structure is an optimization error.
Pydantic object creation is roughly 6.5x slower than standard Python dataclasses, and memory usage
is 2.5x higher because of the validation metadata each instance carries. Use Pydantic at the
boundaries and keep internal processing on dataclasses.

```python
from pydantic import BaseModel

class Item(BaseModel):
    name: str
    price: float
    is_offer: bool | None = None

@app.post("/items/")
async def create_item(item: Item):
    return item
```

## Under the hood: ASGI, Starlette and Uvicorn

**FastAPI** is a subclass of Starlette. Starlette handles the web routing and WebSocket
layers while Pydantic manages the data logic, and FastAPI is the layer that wires them together.
This "Starlette on steroids" approach means any Starlette feature — background tasks, CORS,
startup and shutdown events — is natively available, and it inherits Starlette's 100% test coverage.

![The layers beneath FastAPI: a request travels from the client through Uvicorn, across the ASGI standard, into Starlette's router, then FastAPI and Pydantic validate it before the handler runs](https://camnangai.com/articles/fastapi-la-gi/02-en.webp)

The framework is built on ASGI, the Asynchronous Server Gateway Interface, the modern successor to
WSGI. Where WSGI handles requests strictly one at a time, ASGI lets a server accept many
connections concurrently without waiting for each to finish. That standard is also what keeps
servers interchangeable: Uvicorn, Daphne, and Hypercorn all speak it.

Uvicorn is the recommended server, built on `uvloop` and `httptools` for maximum performance. Under
high concurrency, `uvloop` can handle 2–4x more throughput than the default Python `asyncio` loop by
offloading event management to an optimized C library. The result is a short request pipeline that
makes Python viable for high-throughput
[back-end](https://camnangai.com/en/engineering/what-is-backend-development) systems. Most of that speed is inherited
rather than invented: Starlette and Uvicorn do the heavy lifting, and what FastAPI contributes is
not getting in their way.

## async def or def: how FastAPI handles concurrency

The choice between `async def` and `def` comes down to the nature of the wait, and the official
documentation illustrates it with burgers:

- **Concurrency** — you order, take a number, and go sit with your crush while the kitchen works.
  You get other things done during the wait. This is I/O: database calls, external APIs.
- **Parallelism** — eight cooks work at once, but you stand at the counter until your order is
  handed over. Nothing else gets done while you wait. This is CPU-bound work.

The practical rule follows from that. Use `async def` when you are awaiting I/O, so the event loop
can serve other requests during the wait. Use plain `def` for CPU-bound or blocking work: FastAPI
detects it and offloads the function to an external thread pool, which defaults to 40 threads, so
the main event loop stays free.

The failure mode to avoid is putting heavy CPU-bound work inside an `async def` function. That
blocks the entire event loop and stalls every other request on the server: the endpoint looks
asynchronous at the syntax level while behaving worse than a synchronous one.

```python
# GOOD: async for I/O-bound work
@app.get("/external-api")
async def call_api():
    results = await client.get("https://api.example.com")
    return results

# GOOD: sync for CPU-bound work
@app.get("/compute")
def do_math():
    return heavy_computation()
```

## Depends: dependency injection in FastAPI

The dependency injection system is the framework's real engine. Using `Depends()`, you request the
tools a handler needs, such as a database session or the current user, rather than hard-coding the
lookup inside it. The result is modular, reusable code with a clean separation of concerns.

![A dependency such as a database session or JWT check is declared once and injected into many endpoints, and can be swapped for a mock when tests run](https://camnangai.com/articles/fastapi-la-gi/04-en.webp)

Dependency injection in **FastAPI** supports a graph of dependencies, where a dependency can declare
its own sub-dependencies and the framework resolves the initialization order for you. That structure
is what makes it practical for authentication (injecting OAuth2 with JWT validation), persistence
(caching a database connection or settings object as a singleton), and API key or permission checks.

It also pays off in testing. Because dependencies are declared rather than constructed in place, a
test can override any of them with a mock in a single line, swapping a real database for an
in-memory one without touching the endpoint code. The trade-off arrives later, because once the
graph is deep enough, tracing where a given object was actually constructed is harder than reading
a plain function call.

## The mistakes that make FastAPI slow

FastAPI is fast, but poor implementation will erase the advantage. When a service is slower than it
should be, the dependency file is the first place I look.

![Four traps that make FastAPI slow: missing uvloop, the default JSON encoder, overusing BaseHTTPMiddleware, and running a single worker on one CPU core](https://camnangai.com/articles/fastapi-la-gi/05-en.webp)

1. **Optimization gaps.** Failing to install `uvloop` and `httptools` forces Uvicorn onto slower
   Python-based parsers. Note that `uvloop` is not available on Windows, so a Windows-developed
   service deployed to Linux needs its dependency file checked.
2. **Encoding bottlenecks.** Python's default JSON encoder is slow. Setting `ORJSONResponse` as the
   `default_response_class` gives 20–50% faster serialization.
3. **Middleware overhead.** `BaseHTTPMiddleware` wraps every request in extra machinery; writing
   pure ASGI middleware instead is about 40% faster.
4. **Validation overkill.** Returning a Pydantic model when a `response_model` is already declared
   in the decorator validates the same payload twice. Return a plain dictionary and let the
   framework validate once.
5. **Memory mismanagement.** Loading a large dataset fully into memory before responding is a
   failure mode `StreamingResponse` exists to fix: streaming 10,000 records instead of buffering
   them cuts memory use by roughly 99%.

Worth keeping in proportion: the author of these measurements notes that architectural problems —
N+1 queries, missing indexes, absent caching — deliver 10–100x improvements, while these
framework-level fixes deliver 20–50%. Fix the architecture first.

## FastAPI, Flask or Django — which one?

The choice depends on scope rather than on which framework is fastest in a benchmark.

- **Django** — the batteries-included choice. Use it for full-stack apps that need a built-in admin
  panel, complex ORM relationships, or strict security defaults in regulated industries.
- **Flask** — the minimal choice. Use it for small microservices where you want control over every
  layer, or where the team is not working in an `async`/`await` model.
- **FastAPI** — the current default for new API projects. It is the strongest choice for
  high-concurrency APIs, AI and ML model serving, and any project where type safety and
  auto-generated documentation matter.

![Django, Flask and FastAPI compared: Django ships everything for a full web application, Flask stays minimal and flexible, FastAPI is strongest for high-performance APIs](https://camnangai.com/articles/fastapi-la-gi/06-en.webp)

Put plainly: Django gives you the most built-in capability, Flask gives you the most freedom, and
**FastAPI** gives you strong API structure without owning your whole application.

## Where to start with FastAPI

Install the standard package, which brings the framework together with a production server and the
supporting tooling:

```bash
uv add "fastapi[standard]"
```

Then read the official documentation — it is unusually thorough and example-driven, and it is the
fastest route from a first endpoint to a service you would deploy. If you want a framework that is
quick to write, strict about data at the boundary, and generates its own API documentation, **FastAPI**
is the reasonable default today.

## References

- [Features — FastAPI](https://fastapi.tiangolo.com/features/)
- [Concurrency and async / await — FastAPI](https://fastapi.tiangolo.com/async/)
- [Alternatives, Inspiration and Comparisons — FastAPI](https://fastapi.tiangolo.com/alternatives/)
- [fastapi/fastapi — GitHub](https://github.com/fastapi/fastapi)
- [Understanding FastAPI: How Starlette works — DEV Community](https://dev.to/ceb10n/understanding-fastapi-how-starlette-works-43i1)
- [How to Implement Dependency Injection in FastAPI — freeCodeCamp](https://www.freecodecamp.org/news/how-to-implement-dependency-injection-in-fastapi)
- [An Introduction to Using FastAPI — Refine](https://refine.dev/blog/introduction-to-fast-api/)
- [FastAPI Mistakes That Kill Your Performance — DEV Community](https://dev.to/igorbenav/fastapi-mistakes-that-kill-your-performance-2b8k)
- [Django vs Flask vs FastAPI in 2026 — Which to Choose](https://mecanik.dev/en/posts/python-web-framework-comparison-2026-django-vs-flask-vs-fastapi/)
