Building 10 Python Packages for Enterprise FastAPI Apps: What I Learned
Source: Dev.to – Building 10 Python Packages for Enterprise FastAPI Apps: What I Learned

After a year of building enterprise platforms, I kept solving the same problems:
- How do I handle JWT auth with RBAC that actually scales?
- Why does every project need its own logging configuration?
- How do I manage secrets across Azure Key Vault and local development?
- What’s the cleanest way to handle database connection pooling?
So I extracted the patterns into 10 reusable packages and open‑sourced them.
The Netrun Service Library
All packages are MIT‑licensed and available on PyPI:
pip install netrun-auth netrun-logging netrun-config
The Foundation Layer
netrun-logging – Structured logging that doesn’t suck
- Built on structlog for ~2.9× performance improvement over the standard library.
- Key feature: automatic redaction of sensitive fields.
from netrun_logging import get_logger
logger = get_logger(__name__)
# The password field is automatically redacted
logger.info(
"user_login",
username="daniel",
password="secret123", # Logged as "password": "[REDACTED]"
ip_address="192.168.1.1",
)
netrun-errors – Exception hierarchy that maps to HTTP
- Use typed errors instead of generic
Exceptions. - Each error class corresponds to an appropriate HTTP status code.
from netrun_errors import NotFoundError, ValidationError
from fastapi import FastAPI
app = FastAPI()
@app.get("/users/{user_id}")
async def get_user(user_id: str):
user = await db.get_user(user_id)
if not user:
# Raises a 404 response automatically
raise NotFoundError("User", user_id)
return user
The Auth Layer
netrun-auth – JWT + RBAC + Multi‑tenant isolation
This was the hardest component to get right. It uses Casbin for policy‑based access control.
from netrun_auth import JWTAuthenticator, require_permission
auth = JWTAuthenticator(
secret_key="your-secret",
algorithm="HS256"
)
@app.get("/admin/users")
@require_permission("users:read")
async def list_users(user=Depends(auth.get_current_user)):
# Only users with the `users:read` permission can access this endpoint
return await get_users()
The multi‑tenant isolation ensures that users can only access data belonging to their own tenant:
@require_tenant_access
async def get_tenant_data(tenant_id: str, user=Depends(auth.get_current_user)):
# Automatically validates: user.tenant_id == tenant_id
return await db.get_tenant_data(tenant_id)
JWTAuthenticator– handles token creation/validation.require_permission– decorator that checks the required Casbin permission.require_tenant_access– decorator that enforces tenant‑level isolation.
The Config Layer
netrun-config – Azure Key Vault with local fallback
Works in production with Azure Key Vault and locally with .env files:
from netrun_config import AzureKeyVaultConfig
config = AzureKeyVaultConfig(
vault_url="https://my-vault.vault.azure.net",
cache_ttl=300, # Cache secrets for 5 minutes
)
# In production: fetches from Key Vault
# Locally: falls back to environment variables
db_password = await config.get_secret("database-password")
- Production – Secrets are retrieved directly from Azure Key Vault.
- Local development – If the vault cannot be reached, the config falls back to environment variables (e.g., those loaded from a
.envfile).
The LLM Layer
netrun-llm – Multi‑provider orchestration
netrun‑llm abstracts away the differences between LLM providers, allowing you to switch or fall back between them seamlessly.
from netrun_llm import LLMOrchestrator
llm = LLMOrchestrator(
providers=["azure-openai", "ollama", "claude"],
fallback_enabled=True,
)
# Automatically fails over if the primary provider is down
response = await llm.complete(
prompt="Summarize this document",
model="gpt-4",
fallback_model="llama2", # Use Ollama if Azure is down
)
The Data Layer
netrun-db-pool – Async SQLAlchemy that Handles Connection Storms
Connection pooling with automatic health checks
from netrun_db_pool import DatabasePool
pool = DatabasePool(
url="postgresql+asyncpg://...",
pool_size=20,
max_overflow=10,
health_check_interval=30,
)
async with pool.session() as session:
result = await session.execute(query)
url– Database connection string.pool_size– Number of connections kept open permanently.max_overflow– Additional connections that can be created when the pool is exhausted.health_check_interval– Seconds between automatic health‑check pings to keep connections alive.
The Design Philosophy
Soft Dependencies
Each package works on its own, but when several packages are installed they automatically integrate with one another:
| Packages | Result |
|---|---|
netrun-auth + netrun-logging | Auth events are automatically logged |
netrun-config + netrun-logging | Secret access is audited |
netrun-db-pool + netrun-errors | Connection errors are typed |
The integration is performed at runtime via a simple detection pattern:
try:
from netrun_logging import get_logger
logger = get_logger(__name__)
except ImportError: # Fallback to the standard library
import logging
logger = logging.getLogger(__name__)
Zero‑Config Defaults
Every package ships with sensible defaults, so you can start using them immediately without any configuration:
from netrun_auth import JWTAuthenticator
# Works out‑of‑the‑box
auth = JWTAuthenticator()
# Full customisation when you need it
auth = JWTAuthenticator(
secret_key="…",
algorithm="RS256",
issuer="my-app",
audience=["api", "web"]
)
Testing First
netrun-pyte – a test‑first utility that ships with the suite (content omitted for brevity).
…additional details about the testing approach would follow here…
st‑fixtures – Unified Test Fixtures
# conftest.py
pytest_plugins = ["netrun_pytest_fixtures"]
# Your tests automatically get:
# - mock_auth: Pre‑configured auth bypass
# - mock_db: In‑memory SQLite
# - mock_config: Environment‑based config
# - mock_llm: Deterministic LLM responses
What’s Next
I’m actively maintaining these packages. Current priorities:
- Better documentation – the READMEs are a start, but a full docs site is coming.
- More LLM providers – adding Anthropic Claude API, Google Gemini, etc.
- OpenTelemetry tracing – unified tracing across all packages.
Try It Out
pip install netrun-auth netrun-logging netrun-config
GitHub: https://github.com/your‑org/st‑fixtures
PyPI: https://pypi.org/project/st‑fixtures/
MIT licensed. Issues and PRs are welcome!
What patterns do you use for cross‑cutting concerns in your FastAPI apps? I’d love to hear what I’m missing.
