14 Multi-Client Architecture
Q: Let’s say I have a mono-repo app that structure the frontend and backend like this:
central_repo * frontend/
* backend/
The frontend talk with the backend via REST HTTP request with basepath/api/
endpoint, so that there will be no CORS issue.
In terms of micro-service architecture, can I also use backend as a stand-alone API that other clients can connect to (which could structure their repo similar to this). If it can, I’m not sure if this is a best practice in the industry.
Please give your comment and suggest the best practice.
Great question! Yes, you can absolutely use your backend as a standalone API that serves multiple clients. This is actually a very common and recommended pattern in modern software architecture. Let me break this down with some diagrams and best practices.
14.1 Current Architecture vs Multi-Client Architecture
Your Current Setup:
┌─────────────────────────┐
│ central_repo/ │
│ ┌──────────────────┐ │
│ │ frontend/ │ │
│ └────────┬─────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────┐ │
│ │ backend/ │ │
│ │ /api/* routes │ │
│ └──────────────────┘ │
└─────────────────────────┘
Multi-Client Architecture:
┌─────────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ Your Frontend │ │ Mobile App │ │ 3rd Party App │
│ (Same repo) │ │ (Other repo) │ │ (External) │
└──────────┬──────────┘ └────────┬─────────┘ └────────┬─────────┘
│ │ │
│ ┌───────────────┴───────────────┐ │
└────────►│ Backend API │◄────── ┘
│ (central_repo/backend) │
│ │
│ • /api/v1/users │
│ • /api/v1/products │
│ • /api/v1/orders │
└───────────────────────────────┘
14.2 Best Practices for Multi-Client API
14.2.1 1. API Versioning
# backend/routes/api.py
from fastapi import APIRouter
# Version your API endpoints
= APIRouter(prefix="/api/v1")
v1_router = APIRouter(prefix="/api/v2") # When breaking changes occur v2_router
14.2.3 3. Repository Structure Enhancement
central_repo/
├── frontend/
│ ├── src/
│ └── package.json
├── backend/
│ ├── api/
│ │ ├── v1/
│ │ │ ├── routes/
│ │ │ ├── schemas/
│ │ │ └── middleware/
│ │ └── v2/
│ ├── core/
│ │ ├── config.py
│ │ ├── security.py
│ │ └── database.py
│ ├── services/
│ └── requirements.txt
├── shared/ # Shared types/contracts
│ └── api-specs/
│ └── openapi.yaml
└── docker-compose.yml
14.2.4 4. CORS Configuration for Multiple Clients
# backend/core/config.py
from pydantic import BaseSettings
class Settings(BaseSettings):
# Different CORS origins for different environments
list = [
ALLOWED_ORIGINS: "http://localhost:3000", # Your frontend dev
"https://yourapp.com", # Your production frontend
"https://mobile.yourapp.com", # Mobile web client
"https://partner.example.com" # Partner integration
]
# API Keys for external clients
dict = {
API_KEYS: "mobile_app": "key_xxx",
"partner_app": "key_yyy"
}
14.2.5 5. Different Access Patterns
┌─────────────────────────────────────────────────────┐
│ Client Types │
├─────────────────────────────────────────────────────┤
│ │
│ Internal Frontend: │
│ • Full access to all endpoints │
│ • Session-based auth │
│ • No rate limiting │
│ │
│ Mobile App: │
│ • JWT token auth │
│ • Specific endpoint access │
│ • Moderate rate limiting │
│ │
│ External Partners: │
│ • API Key auth │
│ • Limited endpoint access │
│ • Strict rate limiting │
│ • Webhook callbacks │
│ │
└─────────────────────────────────────────────────────┘
14.3 Implementation Recommendations
14.3.1 1. Use API Gateway Pattern (Optional but Recommended for Scale)
┌─────────────┐
│ Clients │
└──────┬──────┘
▼
┌──────────────────────┐
│ API Gateway │ ← Kong, AWS API Gateway, Traefik
│ • Authentication │
│ • Rate Limiting │
│ • Request Routing │
└──────────┬───────────┘
▼
┌──────────────────────┐
│ Your Backend │
└──────────────────────┘
14.3.2 2. API Documentation
# Use FastAPI's automatic OpenAPI/Swagger generation
from fastapi import FastAPI
= FastAPI(
app ="Your API",
title="1.0.0",
version="/api/docs", # Swagger UI
docs_url="/api/redoc" # ReDoc
redoc_url )
14.3.3 3. Environment-Specific Configuration
# backend/.env.development
=internal
API_MODE=false
RATE_LIMIT_ENABLED
# backend/.env.production
=public
API_MODE=true
RATE_LIMIT_ENABLED=100
RATE_LIMIT_REQUESTS=3600 # per hour RATE_LIMIT_PERIOD
14.4 Is This Best Practice?
YES, absolutely! This pattern is called API-First Development and is considered a best practice because:
- Separation of Concerns: Backend logic is completely decoupled from frontend
- Reusability: One API serves multiple clients
- Scalability: Can scale frontend and backend independently
- Flexibility: Easy to add new client types (mobile, desktop, IoT)
- Testing: API can be tested independently
- Documentation: Single source of truth for API behavior
14.5 Common Patterns in Industry
- Netflix: Single API serving web, mobile, TV apps
- Spotify: Web API serving multiple platforms
- GitHub: Public API used by their own frontend and thousands of external apps
Your monorepo structure with this multi-client capability is actually quite modern and aligns well with current industry practices!