ADR-05: FastAPI single-process architectureΒΆ
ContextΒΆ
TINO needed a Python web framework to serve the REST API and WebSocket endpoints. The main candidates were:
Separately, modern web applications are often split into multiple services: a frontend server, an API server, a WebSocket server, and so on. The question was whether TINO should follow that pattern.
DecisionΒΆ
TINO uses FastAPI with Uvicorn as the ASGI server, running as a single process. The same application serves the REST API, the WebSocket collaboration endpoints, and the static frontend files. There is no separate build pipeline, reverse proxy (in development), or inter-service communication.
ConsequencesΒΆ
PositiveΒΆ
- Simple deploymentA single container with a single volume is all that is needed β no service mesh, no orchestration, no inter-service networking to configure.
- Simple developmentOne process to start, one log stream to watch, one thing to restart.
- Automatic API docsOpenAPI (Swagger UI, ReDoc) is generated automatically from type hints and docstrings, with zero additional effort.
- Dependency injectionFastAPIβs
Depends()system makes service wiring, authentication, and per-request state clean and testable. - Type-safe request/responsePydantic models validate all incoming and outgoing data at the boundary, catching errors early.
- Async-nativeFastAPI is built on ASGI, making it a natural fit for WebSocket support and concurrent I/O β both required for real-time collaboration.
- No distributed stateThe Yjs collaboration manager, the file service, and the API all share the same process memory β no message broker or shared cache required.
NegativeΒΆ
- Younger ecosystemFastAPI is newer than Flask or Django; some integrations and patterns are less established.
- Pydantic couplingHeavy reliance on Pydantic means a major Pydantic version bump can require widespread model updates.
- Vertical scaling onlyThe collaboration manager holds per-file state in process memory, making horizontal scaling across multiple instances non-trivial.
- Single point of failureA crash or restart affects all functionality simultaneously β API, collaboration, and the frontend become unavailable together.