API · lifecycle · FastAPI + PostgreSQL
Every API is a conversation with a contract.
An API is the structured agreement that lets software ask for data, perform an action and receive a predictable response. This overview follows that conversation from a Python client, through FastAPI, into PostgreSQL—and safely back again.
requests.get(url)@app.get('/posts')SELECT · INSERT · UPDATEThe network grid
The complete system is easier to understand as one connected route: a client sends a request, the server interprets it, the database persists the result and a response travels back.
The conversation
A request starts with a client, crosses a network boundary, is interpreted by a server and may read or write persistent data before a response returns.
Client → server
The method, URL, headers and optional body describe what the client wants.
Server ↔ database
The server validates the input, applies business rules and runs the required SQL.
Server → client
An HTTP status and usually a JSON payload report the result in a machine-readable form.
HTTP is the shared vocabulary
The URL identifies a resource. The method describes the intended action. The status code tells the client what happened.
| Method | CRUD | Typical success | Intent |
|---|---|---|---|
| GET | Read | 200 OK | Return a resource or collection. |
| POST | Create | 201 Created | Accept new data and save it. |
| PUT / PATCH | Update | 200 OK / 204 No Content | Replace or modify an existing resource. |
| DELETE | Delete | 204 No Content | Remove the identified resource. |
The client builds and defends the request
Python's requests library handles URL parameters, headers, JSON encoding and response parsing—but robust clients still assume networks and servers can fail.
import requests params = {'page': 2} headers = {'Authorization': 'Bearer …'} response = requests.get( url, params=params, headers=headers, timeout=10, ) response.raise_for_status() data = response.json()
Never assume success
Use a timeout, raise for non-success responses, catch request exceptions, log useful context and retry only when the operation is safe to repeat.
FastAPI turns routes into contracts
Uvicorn listens for network traffic. FastAPI maps a method and path to Python logic. Pydantic validates incoming data before that logic touches the database.
Invalid data fails early.
Missing or mismatched fields produce a clear 422 response. The same route definitions and schemas also generate interactive Swagger documentation at /docs.
Persistence makes the result survive
Objects kept only in application memory disappear on a restart. PostgreSQL stores structured rows on disk so the data remains independent of the server process.
SELECT
SELECT id, name FROM products WHERE price > 20 ORDER BY inventory DESC;
INSERT
INSERT INTO products (name, price, inventory) VALUES ('tortilla', 4, 1000);
Types must agree
Python str, int, float, bool and datetime map to compatible PostgreSQL column types.
Primary keys
A stable unique ID lets routes retrieve, update or delete one exact record without ambiguity.
One operation, seen across every layer
Frameworks and databases use different syntax, but the underlying operation remains the same from the client call to the SQL statement.
| Action | Python client | FastAPI route | PostgreSQL |
|---|---|---|---|
| Create | requests.post() | @app.post() | INSERT |
| Read | requests.get() | @app.get() | SELECT |
| Update | requests.put() | @app.put() | UPDATE |
| Delete | requests.delete() | @app.delete() | DELETE |
The durable mental model
Client asks. Server validates. Logic decides. Database persists. Server assembles a response. Client checks the status and safely consumes the JSON. That pattern survives changes in language, framework and database.