Microservices, APIs
& CI/CD
Learn how software talks to software โ from REST fundamentals to hands-on FastAPI endpoints and automated deployments.
10
Sections
100
MCQs
CRUD
Examples
Foundation
Prerequisites
Before diving in, make sure you have a few basics in place. Think of these as the tools in your toolbox โ you don't need to be an expert, but familiarity helps.
Required knowledge
- Basic computer literacy (files, folders, browsers)
- Elementary programming concepts (variables, functions)
- Comfort using a terminal / command line
Tools to install
- Python 3.10+ โ python.org
- pip โ comes with Python
- A code editor โ VS Code, Cursor, etc.
- Git โ for version control & CI/CD
Quick start check: Open a terminal and run
python --version.
If you see a version number, you're ready to proceed.
Core concept
What Is an API?
API stands for Application Programming Interface. In plain English: it's a menu that one program offers to another. Your app doesn't need to know how the kitchen cooks โ it just orders from the menu and gets a result back.
When you use a weather app, it doesn't measure temperature itself. It calls a weather service's API: "Give me the forecast for London." The API returns structured data (usually JSON), and the app displays it.
Web standards
REST & HTTP Methods
REST (Representational State Transfer) is a popular style for building web APIs. Resources (users, orders, products) are identified by URLs, and you use standard HTTP methods to act on them โ like verbs in a sentence.
| Method | Purpose | Analogy |
|---|---|---|
| GET | Read data | Look at a menu |
| POST | Create new data | Place a new order |
| PUT / PATCH | Update existing data | Change your order |
| DELETE | Remove data | Cancel the order |
Status codes tell you what happened: 200 OK means success,
404 Not Found means the resource doesn't exist,
and 500 Server Error means something broke on the server.
Architecture
Introduction to Microservices
Imagine a restaurant that used to be one giant kitchen where one chef did everything. A monolith app works the same way โ one big codebase handles users, payments, inventory, and shipping.
Microservices split that kitchen into specialized stations: a pastry station, a grill, a salad bar. Each service is a small, independent app with its own database, deployed and scaled separately. They talk to each other through APIs.
โ๏ธ Benefits & trade-offs
- + Teams can deploy services independently
- + Scale only the busy parts (e.g., payment service during sales)
- โ More moving parts = more DevOps complexity
- โ Network calls between services can fail โ you need resilience patterns
DevOps
CI/CD & Automation
CI/CD stands for Continuous Integration and Continuous Delivery/Deployment. Instead of manually copying code to a server every Friday, automation pipelines test and deploy your API whenever you push to Git.
- CI โ automatically run tests & lint on every commit
- CD โ automatically deploy passing builds to staging or production
Popular tools: GitHub Actions, GitLab CI, Jenkins, CircleCI.
For APIs, pipelines often run unit tests with pytest,
build Docker images, and deploy to cloud platforms.
Hands-on
FastAPI & uvicorn Setup
FastAPI is a modern Python framework for building APIs. It's fast, automatically generates interactive docs, and uses Python type hints for validation. uvicorn is the ASGI server that actually runs your FastAPI app.
Installation
pip install fastapi uvicorn[standard]
Minimal app (main.py)
from fastapi import FastAPI
app = FastAPI(title="My API")
@app.get("/")
def read_root():
return {"message": "Hello, API!"}
Run with uvicorn
uvicorn main:app --reload --host 0.0.0.0 --port 8000
Visit http://127.0.0.1:8000/docs for auto-generated Swagger UI.
Section 07
GET Endpoints โ Reading Data
GET requests retrieve data without changing anything. Use path parameters for specific resources and query parameters for filtering.
from fastapi import FastAPI
from typing import List
app = FastAPI()
# In-memory "database" for learning
items_db = [
{"id": 1, "name": "Laptop", "price": 999.99},
{"id": 2, "name": "Mouse", "price": 29.99},
]
@app.get("/items", response_model=List[dict])
def list_items(skip: int = 0, limit: int = 10):
"""GET all items with pagination."""
return items_db[skip : skip + limit]
@app.get("/items/{item_id}")
def get_item(item_id: int):
"""GET a single item by ID."""
for item in items_db:
if item["id"] == item_id:
return item
from fastapi import HTTPException
raise HTTPException(status_code=404, detail="Item not found")
๐ Try it
curl http://localhost:8000/items
curl http://localhost:8000/items/1
Section 08
POST Endpoints โ Creating Data
POST sends a JSON body to create a new resource. FastAPI uses Pydantic models to validate incoming data automatically.
from fastapi import FastAPI, status
from pydantic import BaseModel
app = FastAPI()
items_db = []
next_id = 1
class ItemCreate(BaseModel):
name: str
price: float
@app.post("/items", status_code=status.HTTP_201_CREATED)
def create_item(item: ItemCreate):
global next_id
new_item = {"id": next_id, **item.model_dump()}
items_db.append(new_item)
next_id += 1
return new_item
๐ Try it
curl -X POST http://localhost:8000/items \
-H "Content-Type: application/json" \
-d '{"name": "Keyboard", "price": 79.99}'
DEL
Section 09
PUT/PATCH & DELETE โ Edit & Remove
PUT replaces an entire resource; PATCH updates only the fields you send. DELETE removes a resource.
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from typing import Optional
app = FastAPI()
items_db = [{"id": 1, "name": "Laptop", "price": 999.99}]
class ItemUpdate(BaseModel):
name: Optional[str] = None
price: Optional[float] = None
def find_item(item_id: int):
for i, item in enumerate(items_db):
if item["id"] == item_id:
return i, item
raise HTTPException(status_code=404, detail="Item not found")
@app.put("/items/{item_id}")
def replace_item(item_id: int, data: ItemUpdate):
"""Full replace โ all fields required in practice."""
idx, _ = find_item(item_id)
updated = {"id": item_id, **data.model_dump(exclude_unset=True)}
items_db[idx] = updated
return updated
@app.patch("/items/{item_id}")
def patch_item(item_id: int, data: ItemUpdate):
"""Partial update โ only sent fields change."""
idx, item = find_item(item_id)
patch_data = data.model_dump(exclude_unset=True)
items_db[idx] = {**item, **patch_data}
return items_db[idx]
@app.delete("/items/{item_id}", status_code=204)
def delete_item(item_id: int):
idx, _ = find_item(item_id)
items_db.pop(idx)
return None
๐ Try it
curl -X PATCH http://localhost:8000/items/1 -H "Content-Type: application/json" -d '{"price": 899.99}'
curl -X DELETE http://localhost:8000/items/1
Ship it
Production, Testing & CI/CD
A complete microservice isn't just endpoints โ it needs tests, containers, and automated deployment.
Example pytest test
from fastapi.testclient import TestClient
from main import app
client = TestClient(app)
def test_read_items():
response = client.get("/items")
assert response.status_code == 200
assert isinstance(response.json(), list)
GitHub Actions snippet
# .github/workflows/ci.yml
name: API CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- run: pip install fastapi uvicorn pytest httpx
- run: pytest
โจ Key takeaways
- โ APIs are contracts โ document them (FastAPI does this automatically)
- โ Microservices communicate over HTTP/gRPC โ design for failure
- โ Automate testing and deployment early โ CI/CD saves hours later
- โ Start simple (monolith or few services), split when you have a clear reason