premier turns your ASGI server into a full-featured API gateway.
Premier is a versatile Python toolkit that can be used in three main ways:
Premier transforms any Python web application into a full-featured API gateway with caching, rate limiting, retry logic, timeouts, and performance monitoring.
Premier comes with a nice dashboard for you to monitor your requests
π Complete Documentation Site - Full documentation with examples, tutorials, and API reference
Quick links:
Premier provides enterprise-grade API gateway functionality with:
β¦ and more
Premier is designed for simplicity and accessibility - perfect for simple applications that need API gateway functionality without introducing complex tech stacks like Kong, Ambassador, or Istio.
Key advantages:
How it works: Each app instance has its own Premier gateway wrapper
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β App Instance 1 β
β βββββββββββββββββββ βββββββββββββββββββββββββββββββββββ β
β β Premier ββββββ Your ASGI App β β
β β Gateway β β (FastAPI/Django/etc) β β
β β ββββββββββββ β β β β
β β βCache β β β @app.get("/api/users") β β
β β βRateLimit β β β async def get_users(): β β
β β βRetry β β β return users β β
β β βTimeout β β β β β
β β ββββββββββββ β β β β
β βββββββββββββββββββ βββββββββββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
You can keep your existing app.py file untouched
# app.py
from premier.asgi import ASGIGateway, GatewayConfig
from fastapi import FastAPI
# Your existing app - no changes needed
app = FastAPI()
@app.get("/api/users/{user_id}")
async def get_user(user_id: int):
return await fetch_user_from_database(user_id)
Next, import your app instance and wrap it with ASGIGateway:
# gateway.py
from .app import app
# Load configuration and wrap app
config = GatewayConfig.from_file("gateway.yaml")
app = ASGIGateway(config=config, app=app)
Then, instead of serving the original app directly, serve the one wrapped with ASGIGateway.
How it works: Single gateway handles all requests and forwards to backend services
βββββββββββββββββββββββ
Client Request β Premier Gateway β
β β ββββββββββββββββ β
β β β Cache β β
ββββββββββββββββΊ β RateLimit β β
β β Retry β β
β β Timeout β β
β β Monitoring β β
β ββββββββββββββββ β
βββββββ¬βββββββ¬βββββββββ
β β
βββββββββββ βββββββββββ
βΌ βΌ
βββββββββββββββββ βββββββββββββββββ
β Backend 1 β β Backend 2 β
β (Any Service) β β (Any Service) β
β β β β
β Node.js API β β Python API β
β Java Service β β .NET Service β
β Static Files β β Database β
βββββββββββββββββ βββββββββββββββββ
# main.py
from premier.asgi import ASGIGateway, GatewayConfig
config = GatewayConfig.from_file("gateway.yaml")
gateway = ASGIGateway(config, servers=["http://backend:8000"])
uvicorn src:main
How it works: Apply Premier features directly to individual functions with decorators - no ASGI app required
Premier supports WebSocket connections with the same feature set:
# WebSocket connections are automatically handled
# Configure WebSocket-specific policies in YAML:
premier:
paths:
- pattern: "/ws/chat/*"
features:
rate_limit:
quota: 100 # Max 100 connections per minute
duration: 60
monitoring:
log_threshold: 5.0 # Log connections lasting >5s
Configure gateway policies declaratively:
premier:
keyspace: "my-api"
paths:
- pattern: "/api/users/*"
features:
cache:
expire_s: 300
rate_limit:
quota: 100
duration: 60
algorithm: "sliding_window"
timeout:
seconds: 5.0
retry:
max_attempts: 3
wait: 1.0
monitoring:
log_threshold: 0.1
- pattern: "/api/admin/*"
features:
rate_limit:
quota: 10
duration: 60
algorithm: "token_bucket"
timeout:
seconds: 30.0
- pattern: "/ws/*"
features:
rate_limit:
quota: 50
duration: 60
algorithm: "sliding_window"
monitoring:
log_threshold: 1.0
default_features:
timeout:
seconds: 10.0
monitoring:
log_threshold: 0.5
Premier supports extensive configuration options for path-based policies. Hereβs a complete reference of all available configuration fields:
Field | Type | Description | Default |
---|---|---|---|
keyspace |
string | Namespace for cache keys and throttling | "asgi-gateway" |
paths |
array | Path-specific configuration rules | [] |
default_features |
object | Default features applied to all paths | null |
servers |
array | Backend server URLs for standalone mode | null |
Field | Type | Description | Example |
---|---|---|---|
pattern |
string | Path pattern (regex or glob-style) | "/api/users/*" , "^/admin/.*$" |
features |
object | Features to apply to this path | See feature configuration below |
Field | Type | Description | Default | Example |
---|---|---|---|---|
expire_s |
integer | Cache expiration in seconds | null (no expiration) |
300 |
cache_key |
string/function | Custom cache key | Auto-generated | "user:{user_id}" |
Field | Type | Description | Default | Example |
---|---|---|---|---|
quota |
integer | Number of requests allowed | Required | 100 |
duration |
integer | Time window in seconds | Required | 60 |
algorithm |
string | Rate limiting algorithm | "fixed_window" |
"sliding_window" , "token_bucket" , "leaky_bucket" |
bucket_size |
integer | Bucket size (for leaky_bucket) | Same as quota | 50 |
error_status |
integer | HTTP status code for rate limit errors | 429 |
503 |
error_message |
string | Error message for rate limit errors | "Rate limit exceeded" |
"Too many requests" |
Field | Type | Description | Default | Example |
---|---|---|---|---|
seconds |
float | Timeout duration in seconds | Required | 5.0 |
error_status |
integer | HTTP status code for timeout errors | 504 |
408 |
error_message |
string | Error message for timeout errors | "Request timeout" |
"Request took too long" |
Field | Type | Description | Default | Example |
---|---|---|---|---|
max_attempts |
integer | Maximum retry attempts | 3 |
5 |
wait |
float/array/function | Wait time between retries | 1.0 |
[1, 2, 4] |
exceptions |
array | Exception types to retry on | [Exception] |
Custom exceptions |
Field | Type | Description | Default | Example |
---|---|---|---|---|
failure_threshold |
integer | Failures before opening circuit | 5 |
10 |
recovery_timeout |
float | Seconds before attempting recovery | 60.0 |
120.0 |
expected_exception |
string | Exception type that triggers circuit | "Exception" |
"ConnectionError" |
Field | Type | Description | Default | Example |
---|---|---|---|---|
log_threshold |
float | Log requests taking longer than this (seconds) | 0.1 |
1.0 |
premier:
keyspace: "production-api"
servers: ["http://backend1:8000", "http://backend2:8000"]
paths:
- pattern: "/api/users/*"
features:
cache:
expire_s: 300
rate_limit:
quota: 1000
duration: 60
algorithm: "sliding_window"
error_status: 429
error_message: "Rate limit exceeded for user API"
timeout:
seconds: 5.0
error_status: 504
error_message: "User API timeout"
retry:
max_attempts: 3
wait: [1, 2, 4] # Exponential backoff
circuit_breaker:
failure_threshold: 5
recovery_timeout: 60.0
monitoring:
log_threshold: 0.1
- pattern: "/api/admin/*"
features:
rate_limit:
quota: 10
duration: 60
algorithm: "token_bucket"
error_status: 403
error_message: "Admin API rate limit exceeded"
timeout:
seconds: 30.0
error_status: 408
error_message: "Admin operation timeout"
monitoring:
log_threshold: 0.5
default_features:
timeout:
seconds: 10.0
rate_limit:
quota: 100
duration: 60
algorithm: "fixed_window"
monitoring:
log_threshold: 1.0
fixed_window
: Simple time-based windowssliding_window
: Smooth rate limiting over timetoken_bucket
: Burst capacity with steady refill rateleaky_bucket
: Queue-based rate limiting with controlled drainingpip install premier
For Redis support (optional):
pip install premier[redis]
Premier includes powerful decorators for adding resilience to individual functions:
from premier.retry import retry
@retry(max_attempts=3, wait=1.0, exceptions=(ConnectionError, TimeoutError))
async def api_call():
# Your function with retry logic
return await make_request()
from premier.timer import timeit, timeout
@timeit(log_threshold=0.1) # Log calls taking >0.1s
async def slow_operation():
return await heavy_computation()
@timeout(seconds=5) # Timeout after 5 seconds
async def time_limited_task():
return await long_running_operation()
Works with any ASGI framework:
# FastAPI
from fastapi import FastAPI
app = FastAPI()
# Starlette
from starlette.applications import Starlette
app = Starlette()
# Django ASGI
from django.core.asgi import get_asgi_application
app = get_asgi_application()
# Wrap with Premier
config = GatewayConfig.from_file("config.yaml")
gateway = ASGIGateway(config, app=app)
# production.py
from premier.asgi import ASGIGateway, GatewayConfig
from premier.providers.redis import AsyncRedisCache
from redis.asyncio import Redis
# Redis backend for distributed caching
redis_client = Redis.from_url("redis://localhost:6379")
cache_provider = AsyncRedisCache(redis_client)
# Load configuration
config = GatewayConfig.from_file("production.yaml")
# Create production gateway
gateway = ASGIGateway(config, app=your_app, cache_provider=cache_provider)
# Deploy with uvicorn
if __name__ == "__main__":
import uvicorn
uvicorn.run(gateway, host="0.0.0.0", port=8000, workers=4)
MIT License