A Python microservices framework with FastAPI-like interface for seamless inter-service communication
Project description
MicroAPI
MicroAPI is a Python microservices framework that lets your services communicate as if calling regular Python functions. Built with a FastAPI-like interface, full Pydantic typing, and multiple transport backends.
from microapi import MicroAPI, Service, Schema
from microapi.transport.http import HTTPTransport
class User(Schema):
username: str
age: int = 0
service = Service("users")
@service.method
async def get_user(payload: GetUserPayload) -> User:
return User(username="alice", age=30)
app = MicroAPI(services=[service])
app.run(transport=HTTPTransport(port=8080), auto_generate_lib=True)
On the client side, the auto-generated library gives you full IDE autocompletion:
from lib import users
from microapi.client.base import Connection
from microapi.transport.http import HTTPTransport
async with Connection(HTTPTransport(port=8080).create_client()) as conn:
user = await users.get_user(user_id=1) # fully typed!
print(user.username) # IDE knows this is str
Benchmarks (FastAPI vs MicroAPI)
We run real localhost benchmarks (network stack included) comparing:
- FastAPI over HTTP (
uvicorn+httpx,ORJSONResponse) - MicroAPI over gRPC (custom HTTP/2
h2transport, JSON envelopes)
Plus two extra baselines:
- MicroAPI over HTTP (aiohttp transport)
- raw aiohttp (minimal handler, no framework features)
To reproduce:
uv sync --extra bench --extra http --extra grpc
uv run python -m benchmarks.run
Results vary by machine/OS/Python. The table below is generated by benchmarks/run.py.
| Benchmark | Requests | Total (s) | Req/s | p50 (ms) | p95 (ms) |
|---|---|---|---|---|---|
| FastAPI HTTP (uvicorn + httpx) | 5,000 | 3.298 | 1,516 | 0.645 | 0.754 |
| MicroAPI HTTP (aiohttp) | 5,000 | 0.816 | 6,126 | 0.160 | 0.183 |
| MicroAPI gRPC (h2, JSON) | 5,000 | 1.513 | 3,304 | 0.299 | 0.345 |
| aiohttp raw HTTP (baseline) | 5,000 | 0.641 | 7,798 | 0.125 | 0.145 |
Run details: macOS-26.2-arm64-arm-64bit-Mach-O, Python 3.13.2, localhost, unary echo RPC, payload (\approx 128) bytes, warmup=500, n=5000.
See benchmarks/README.md for methodology and how to reproduce.
Key Features
| Feature | Description |
|---|---|
| FastAPI-like Interface | @service.method decorator, Pydantic schemas, dependency injection |
| 5 Transports | gRPC (custom h2), HTTP, WebSocket, Kafka, RabbitMQ |
| 4 RPC Patterns | Unary, server streaming, client streaming, bidirectional |
| Auto Code Generation | Typed Python client libraries + .proto files |
| Middleware | Composable middleware chain with full request/response access |
| Dependency Injection | Depends() with caching, async support, request access |
| CLI Tool | microapi run, microapi generate, microapi init, microapi info |
| Hot Reload | Auto-restart on file changes during development |
| Type Safe | Full Pydantic validation + generated client code with type hints |
Installation
pip install microapi # Core framework
pip install microapi[http] # + HTTP transport (aiohttp)
pip install microapi[grpc] # + gRPC transport (h2-based)
pip install microapi[ws] # + WebSocket transport
pip install microapi[kafka] # + Apache Kafka transport
pip install microapi[rabbitmq] # + RabbitMQ transport
pip install microapi[all] # Everything
Quick Start
See the full Getting Started Guide for a complete walkthrough.
1. Define schemas and a service
# schemas.py
from microapi import Schema
class UserPayload(Schema):
user_id: int
class User(Schema):
username: str
age: int = 0
# service.py
from microapi import Service, types
from schemas import UserPayload, User
service = Service("users")
@service.method
async def get_user(payload: UserPayload) -> User:
return User(username="alice", age=30)
@service.method
async def list_users(payload: UserPayload) -> types.Streaming[User]:
for user in await fetch_all_users():
yield user
2. Run the server
# main.py
from microapi import MicroAPI
from microapi.transport.http import HTTPTransport
from service import service
app = MicroAPI(services=[service])
app.run(
transport=HTTPTransport(host="0.0.0.0", port=8080),
auto_generate_lib=True,
generated_lib_dir="lib",
)
3. Use the auto-generated client
import asyncio
from lib import users
from microapi.client.base import Connection
from microapi.transport.http import HTTPTransport
async def main():
transport = HTTPTransport(host="127.0.0.1", port=8080)
async with Connection(transport.create_client()) as conn:
user = await users.get_user(user_id=1)
print(user.username) # IDE autocomplete works!
asyncio.run(main())
Documentation
| Page | Description |
|---|---|
| Getting Started | Installation, first project, step-by-step tutorial |
| Services & Methods | Defining services, method patterns, schemas |
| Transports | HTTP, gRPC, WebSocket, Kafka, RabbitMQ configuration |
| Streaming | All 4 RPC patterns with detailed examples |
| Middleware | Middleware chain, ordering, short-circuiting |
| Dependencies | Depends(), caching, request access, async deps |
| Code Generation | Python client library + Protobuf generation |
| CLI Reference | All CLI commands and options |
| Lifecycle | Startup/shutdown hooks, lifespan context managers |
| Architecture | Wire protocol, design decisions, project structure |
| API Reference | All public classes, methods, and types |
| Examples | Complete working examples for all features |
RPC Patterns at a Glance
# Unary: request → response
@service.method
async def get_user(payload: GetUserPayload) -> User: ...
# Server streaming: request → stream of responses
@service.method
async def list_users(payload: ListPayload) -> types.Streaming[User]: ...
# Client streaming: stream of requests → response
@service.method
async def add_users(stream: types.Stream[User]) -> Result: ...
# Bidirectional: stream ↔ stream
@service.method
async def chat(stream: types.Stream[Message]) -> types.Streaming[Reply]: ...
Transport Comparison
| Transport | Protocol | Streaming | Latency | Use Case |
|---|---|---|---|---|
| gRPC | HTTP/2 | Full | Low | Internal microservices |
| HTTP | HTTP/1.1 | Server only | Medium | REST-like APIs, web clients |
| WebSocket | WS | Full | Low | Real-time, persistent connections |
| Kafka | TCP | Server | High | Event-driven, high throughput |
| RabbitMQ | AMQP | Server | Medium | Task queues, reliable delivery |
Development
git clone https://github.com/BiqRed/MicroAPI.git
cd MicroAPI
uv sync --all-extras
uv run pytest tests/ -v # Run tests
uv run ruff check microapi/ # Lint
uv run mypy microapi/ # Type check
License
MIT
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file microapi-1.1.1.tar.gz.
File metadata
- Download URL: microapi-1.1.1.tar.gz
- Upload date:
- Size: 172.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d4b4286301e6abe4926cd9bccbfd70cbff22251133e8f3cdfca763a38a5c167c
|
|
| MD5 |
ca8fe228ed646b6e30c09f9090a2f927
|
|
| BLAKE2b-256 |
29309ce35a28c43b1448c067e4f22bad4bc8bfdd3ec783965b9d6fa20fbe0ba9
|
Provenance
The following attestation bundles were made for microapi-1.1.1.tar.gz:
Publisher:
release.yml on BiqRed/MicroAPI
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
microapi-1.1.1.tar.gz -
Subject digest:
d4b4286301e6abe4926cd9bccbfd70cbff22251133e8f3cdfca763a38a5c167c - Sigstore transparency entry: 928759702
- Sigstore integration time:
-
Permalink:
BiqRed/MicroAPI@eed870316bbc83800353f3a664bc4fbe357c06b5 -
Branch / Tag:
refs/tags/v1.1.1 - Owner: https://github.com/BiqRed
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@eed870316bbc83800353f3a664bc4fbe357c06b5 -
Trigger Event:
push
-
Statement type:
File details
Details for the file microapi-1.1.1-py3-none-any.whl.
File metadata
- Download URL: microapi-1.1.1-py3-none-any.whl
- Upload date:
- Size: 55.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b9f7709ed1ec8b073f0eb376c5b4b19ad61e852e29ff3256efe9802827bd7871
|
|
| MD5 |
6436f2aaac7db955ef2a1c7205a3aa0e
|
|
| BLAKE2b-256 |
564032338a66340f552a745592f52b2e84a0db97d34621af34091005a0fc4b34
|
Provenance
The following attestation bundles were made for microapi-1.1.1-py3-none-any.whl:
Publisher:
release.yml on BiqRed/MicroAPI
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
microapi-1.1.1-py3-none-any.whl -
Subject digest:
b9f7709ed1ec8b073f0eb376c5b4b19ad61e852e29ff3256efe9802827bd7871 - Sigstore transparency entry: 928759722
- Sigstore integration time:
-
Permalink:
BiqRed/MicroAPI@eed870316bbc83800353f3a664bc4fbe357c06b5 -
Branch / Tag:
refs/tags/v1.1.1 - Owner: https://github.com/BiqRed
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@eed870316bbc83800353f3a664bc4fbe357c06b5 -
Trigger Event:
push
-
Statement type: