FastAPI adalah framework Python modern untuk membangun API yang menggabungkan tiga hal yang jarang ada di satu framework: kecepatan (setara Node.js dan Go), developer experience yang luar biasa, dan dokumentasi API otomatis. Jika Anda membangun microservice untuk model ML, data processing, atau layanan Python apa pun yang perlu dikonsumsi aplikasi lain, FastAPI adalah pilihan yang sangat solid.
Mengapa FastAPI?
- Performance — Berbasis ASGI (Starlette), performa setara Node.js berkat async I/O
- Auto-dokumentasi — Swagger UI dan ReDoc tergenerate otomatis dari code
- Type Safety — Validasi request/response otomatis via Pydantic v2
- Python Type Hints — Full IDE support, autocomplete, dan error detection
- Standards — Mengikuti OpenAPI dan JSON Schema standards
Setup dan Hello World
pip install fastapi uvicorn[standard] pydantic sqlalchemy alembic
# Jalankan server
uvicorn main:app --reload
# main.py
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI(
title="Artikel API",
description="Microservice untuk manajemen konten",
version="1.0.0",
)
class PostCreate(BaseModel):
title: str
content: str
status: str = "draft"
class PostResponse(BaseModel):
id: int
title: str
slug: str
status: str
@app.get("/")
async def root():
return {"message": "API aktif"}
@app.post("/posts", response_model=PostResponse, status_code=201)
async def create_post(post: PostCreate):
# FastAPI otomatis validasi request body
# Dokumentasi Swagger otomatis tersedia di /docs
return {"id": 1, "title": post.title, "slug": "generated-slug", "status": post.status}
Buka http://localhost:8000/docs — Swagger UI sudah tersedia tanpa konfigurasi apapun.
Database dengan SQLAlchemy + Async
pip install sqlalchemy[asyncio] asyncpg # Untuk PostgreSQL
# database.py
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
from sqlalchemy.orm import DeclarativeBase, sessionmaker
DATABASE_URL = "postgresql+asyncpg://user:password@localhost/db"
engine = create_async_engine(DATABASE_URL, echo=True)
AsyncSessionLocal = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
class Base(DeclarativeBase):
pass
# Dependency injection untuk session
async def get_db():
async with AsyncSessionLocal() as session:
try:
yield session
await session.commit()
except Exception:
await session.rollback()
raise
# models.py
from sqlalchemy import String, Text, DateTime, func
from sqlalchemy.orm import Mapped, mapped_column
from database import Base
class Post(Base):
__tablename__ = "posts"
id: Mapped[int] = mapped_column(primary_key=True)
title: Mapped[str] = mapped_column(String(255))
slug: Mapped[str] = mapped_column(String(255), unique=True, index=True)
content: Mapped[str] = mapped_column(Text)
status: Mapped[str] = mapped_column(String(20), default="draft")
created_at: Mapped[DateTime] = mapped_column(DateTime, server_default=func.now())
CRUD Endpoint Lengkap
# routers/posts.py
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select
from database import get_db
from models import Post
from schemas import PostCreate, PostUpdate, PostResponse
router = APIRouter(prefix="/posts", tags=["posts"])
@router.get("/", response_model=list[PostResponse])
async def list_posts(
skip: int = 0,
limit: int = 20,
db: AsyncSession = Depends(get_db),
):
result = await db.execute(
select(Post).where(Post.status == "published").offset(skip).limit(limit)
)
return result.scalars().all()
@router.get("/{post_id}", response_model=PostResponse)
async def get_post(post_id: int, db: AsyncSession = Depends(get_db)):
post = await db.get(Post, post_id)
if not post:
raise HTTPException(status_code=404, detail="Post tidak ditemukan")
return post
@router.post("/", response_model=PostResponse, status_code=201)
async def create_post(data: PostCreate, db: AsyncSession = Depends(get_db)):
post = Post(**data.model_dump())
db.add(post)
await db.flush()
await db.refresh(post)
return post
Autentikasi JWT
pip install python-jose[cryptography] passlib[bcrypt]
# auth.py
from fastapi import Depends, HTTPException, status
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from jose import JWTError, jwt
SECRET_KEY = "your-secret-key"
ALGORITHM = "HS256"
security = HTTPBearer()
async def get_current_user(
credentials: HTTPAuthorizationCredentials = Depends(security),
db: AsyncSession = Depends(get_db),
) -> User:
try:
payload = jwt.decode(credentials.credentials, SECRET_KEY, algorithms=[ALGORITHM])
user_id = payload.get("sub")
if user_id is None:
raise HTTPException(status_code=401, detail="Token tidak valid")
except JWTError:
raise HTTPException(status_code=401, detail="Token tidak valid")
user = await db.get(User, int(user_id))
if not user:
raise HTTPException(status_code=401, detail="User tidak ditemukan")
return user
# Gunakan di route
@router.post("/", response_model=PostResponse)
async def create_post(
data: PostCreate,
current_user: User = Depends(get_current_user),
db: AsyncSession = Depends(get_db),
):
# current_user sudah terautentikasi
post = Post(**data.model_dump(), author_id=current_user.id)
...
Containerize dengan Docker
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
FastAPI cocok sekali sebagai microservice yang di-consume aplikasi Laravel — misalnya untuk layanan ML inference, image processing, atau data analytics yang lebih praktis dikerjakan di Python. Komunikasi antar service bisa via HTTP biasa atau message queue seperti RabbitMQ/Redis.