gRPC Configuration
Complete reference for configuring Django-CFG gRPC integration.
📋 Configuration Structure
# api/config.py
from typing import Optional
from django_cfg import (
DjangoConfig,
GRPCConfig,
GRPCServerConfig,
GRPCKeepaliveConfig,
GRPCConnectionLimitsConfig,
GRPCAuthConfig,
GRPCProtoConfig,
)
class MyConfig(DjangoConfig):
grpc: Optional[GRPCConfig] = GRPCConfig(
enabled=True,
server=GRPCServerConfig(...),
auth=GRPCAuthConfig(...),
proto=GRPCProtoConfig(...),
auto_register_apps=True,
enabled_apps=[...],
)⚙️ GRPCConfig
Main gRPC configuration container.
| Field | Type | Default | Description |
|---|---|---|---|
enabled | bool | False | Enable/disable gRPC server |
server | GRPCServerConfig | - | Server configuration |
auth | GRPCAuthConfig | - | Authentication configuration |
proto | GRPCProtoConfig | - | Protocol Buffer configuration |
tls | TLSConfig | - | TLS/SSL configuration (new!) |
auto_register_apps | bool | True | Auto-discover services |
enabled_apps | list[str] | [] | Apps to scan for services |
| TLS Flatten Fields | |||
tls_enabled | bool | None | Enable TLS (shortcut) |
tls_cert_path | str | None | Server certificate path |
tls_key_path | str | None | Server private key path |
Example
grpc: GRPCConfig = GRPCConfig(
enabled=True,
auto_register_apps=True,
enabled_apps=["apps.users", "apps.products", "apps.orders"],
)🎯 Simplified Configuration (Flatten Fields)
For simpler configs, you can use flatten fields instead of nested config objects:
Traditional (Nested):
grpc = GRPCConfig(
enabled=True,
server=GRPCServerConfig(
host="[::]",
port=50051,
),
proto=GRPCProtoConfig(
package_prefix="api",
output_dir="protos",
),
enabled_apps=["apps.crypto"],
)Simplified (Flatten):
grpc = GRPCConfig(
enabled=True,
enabled_apps=["apps.crypto"],
# Server fields (flatten)
host="[::]", # Instead of server=GRPCServerConfig(host=...)
port=50051,
# Proto fields (flatten)
package_prefix="api", # Instead of proto=GRPCProtoConfig(package_prefix=...)
# Environment integration
public_url=env.grpc_url,
)Benefits:
- Less boilerplate code
- No need to import nested config classes
- Cleaner configuration
- Same functionality
When to use nested: When you need to organize complex configs or reuse config objects. When to use flatten: For simple configs (recommended for most cases).
🖥️ GRPCServerConfig
gRPC server settings.
| Field | Type | Default | Description |
|---|---|---|---|
host | str | "[::]" | Server host address |
port | int | 50051 | Server port |
enable_reflection | bool | True | Enable server reflection |
enable_health_check | bool | True | Enable health check service |
compression | str | None | None | Compression algorithm ("gzip", "deflate") |
max_send_message_length | int | 4MB | Max outbound message size |
max_receive_message_length | int | 4MB | Max inbound message size |
keepalive | GRPCKeepaliveConfig | - | HTTP/2 keepalive settings |
connection_limits | GRPCConnectionLimitsConfig | - | Connection lifecycle limits |
Host Options
# All interfaces (IPv6) - Recommended
host="[::]"
# All interfaces (IPv4)
host="0.0.0.0"
# Localhost only
host="127.0.0.1"
# Specific IP
host="192.168.1.100"Reflection
# Development: Enable for grpcurl testing
enable_reflection=True
# Production: Disable to hide service schema
enable_reflection=FalseHealth Check
# Always recommended for production
enable_health_check=True
# For load balancers
# GET /grpc.health.v1.Health/CheckComplete Example
from django_cfg import GRPCServerConfig, GRPCKeepaliveConfig
server=GRPCServerConfig(
host="[::]", # All interfaces
port=50051, # Standard port
enable_reflection=True, # Enable grpcurl
enable_health_check=True, # Enable health checks
compression="gzip", # Enable gzip compression
# Nested keepalive config for streaming
keepalive=GRPCKeepaliveConfig.for_streaming(),
)🔄 GRPCKeepaliveConfig
HTTP/2 keepalive configuration for connection health and dead connection detection.
from django_cfg import GRPCKeepaliveConfig| Field | Type | Default | Description |
|---|---|---|---|
time_ms | int | 10000 | Keepalive ping interval (ms). How often to send HTTP/2 PING. |
timeout_ms | int | 5000 | Keepalive timeout (ms). How long to wait for PING ACK. |
permit_without_calls | bool | True | Allow pings even without active RPC calls. |
min_time_between_pings_ms | int | 5000 | Minimum time between successive pings (anti-abuse). |
max_pings_without_data | int | 0 | Max pings without data. 0 = unlimited (streaming). |
Factory Methods
# For long-lived bidirectional streaming connections (recommended)
# Optimized: 10s ping, 5s timeout = 15s dead connection detection
keepalive = GRPCKeepaliveConfig.for_streaming()
# For short-lived RPC connections
# Less aggressive: 30s ping, 10s timeout
keepalive = GRPCKeepaliveConfig.for_short_lived()Custom Configuration
keepalive = GRPCKeepaliveConfig(
time_ms=15000, # Ping every 15 seconds
timeout_ms=10000, # Wait 10 seconds for ACK
permit_without_calls=True,
max_pings_without_data=0, # Unlimited for streaming
)Converting to gRPC Options
# Use to_grpc_options() method for low-level gRPC configuration
options = keepalive.to_grpc_options()
# Returns: [("grpc.keepalive_time_ms", 15000), ("grpc.keepalive_timeout_ms", 10000), ...]🔗 GRPCConnectionLimitsConfig
Connection lifecycle limits for server-side connection management.
from django_cfg import GRPCConnectionLimitsConfig| Field | Type | Default | Description |
|---|---|---|---|
max_connection_idle_ms | int | 7200000 | Max idle time (ms) before closing. Default: 2 hours. |
max_connection_age_ms | int | 0 | Max connection age (ms). 0 = unlimited (streaming). |
max_connection_age_grace_ms | int | 300000 | Grace period (ms) for in-flight RPCs. Default: 5 min. |
Example
from django_cfg import GRPCConnectionLimitsConfig
# Default: optimized for long-lived streaming
connection_limits = GRPCConnectionLimitsConfig()
# Custom: shorter limits for REST-like RPC
connection_limits = GRPCConnectionLimitsConfig(
max_connection_idle_ms=3600000, # 1 hour
max_connection_age_ms=86400000, # 24 hours
max_connection_age_grace_ms=60000, # 1 minute
)Streaming Recommendation: For bidirectional streaming, use max_connection_age_ms=0 (unlimited) to prevent premature connection closure during long-running streams.
🔐 GRPCAuthConfig
Authentication configuration (supports API keys).
| Field | Type | Default | Description |
|---|---|---|---|
enabled | bool | False | Enable authentication |
require_auth | bool | False | Require auth for all methods |
| API Key Settings | |||
api_key_header | str | "x-api-key" | Header name for API key |
accept_django_secret_key | bool | True | Accept Django SECRET_KEY as valid API key (for dev/internal use) |
| General | |||
public_methods | list[str] | [] | Public methods (no auth required) |
Authentication Modes
Mode 1: Disabled (Development)
auth=GRPCAuthConfig(
enabled=False, # No authentication
)Mode 2: Optional Auth (Recommended)
auth=GRPCAuthConfig(
enabled=True,
require_auth=False, # Some methods can be public
api_key_header="x-api-key",
accept_django_secret_key=True, # Allow SECRET_KEY for dev
)
# In service:
# - Use self.get_user(context) for optional auth
# - Use self.require_user(context) for protected methods
# - Access context.api_key to check which API key was usedMode 3: Required Auth (Strict - Production)
auth=GRPCAuthConfig(
enabled=True,
require_auth=True, # All methods require API key
api_key_header="x-api-key",
accept_django_secret_key=False, # Production: only DB keys
public_methods=[ # Except these
"/grpc.health.v1.Health/Check",
],
)Public Methods
auth=GRPCAuthConfig(
enabled=True,
require_auth=False,
public_methods=[
# Health check (always public)
"/grpc.health.v1.Health/Check",
"/grpc.health.v1.Health/Watch",
# Your public methods
"/api.users.UserService/GetUser",
"/api.products.ProductService/ListProducts",
],
)Complete Example
# Production configuration with API keys
auth=GRPCAuthConfig(
enabled=True,
require_auth=True, # Strict auth in production
# API key configuration
api_key_header="x-api-key",
accept_django_secret_key=False, # Disable SECRET_KEY in production
# Public methods
public_methods=[
"/grpc.health.v1.Health/Check",
"/grpc.health.v1.Health/Watch",
],
)API Key Settings
Custom Header Name
auth=GRPCAuthConfig(
api_key_header="x-custom-api-key", # Change header name
)Disable SECRET_KEY (Production)
auth=GRPCAuthConfig(
accept_django_secret_key=False, # Only accept keys from database
)Enable SECRET_KEY (Development)
auth=GRPCAuthConfig(
accept_django_secret_key=True, # Allow using settings.SECRET_KEY
)
# Usage:
# grpcurl -H "x-api-key: $(python manage.py shell -c 'from django.conf import settings; print(settings.SECRET_KEY)')" ...📄 GRPCProtoConfig
Protocol Buffer generation settings.
| Field | Type | Default | Description |
|---|---|---|---|
auto_generate | bool | False | Auto-generate proto files |
output_dir | str | "protos" | Proto output directory |
package_prefix | str | "api" | Package prefix |
Example
proto=GRPCProtoConfig(
auto_generate=True,
output_dir="protos",
package_prefix="api",
)
# Generates:
# protos/api/users.proto
# protos/api/products.proto🔒 TLSConfig
TLS/SSL configuration for secure gRPC connections. Supports server-side TLS, client TLS, and mutual TLS (mTLS).
from django_cfg.modules.django_grpc.configs import TLSConfig| Field | Type | Default | Description |
|---|---|---|---|
enabled | bool | False | Enable TLS/SSL |
cert_path | str | None | Server certificate path (.crt/.pem) |
key_path | str | None | Server private key path (.key/.pem) |
ca_cert_path | str | None | CA certificate for verification |
client_cert_path | str | None | Client certificate (mTLS) |
client_key_path | str | None | Client private key (mTLS) |
require_client_cert | bool | False | Require client certificate (server-side mTLS) |
verify_server | bool | True | Verify server certificate (client-side) |
min_version | str | "TLS1.2" | Minimum TLS version |
Server TLS Example
from django_cfg import GRPCConfig
from django_cfg.modules.django_grpc.configs import TLSConfig
grpc = GRPCConfig(
enabled=True,
tls=TLSConfig(
enabled=True,
cert_path="/etc/ssl/server.crt",
key_path="/etc/ssl/server.key",
),
# Or use flatten fields:
# tls_enabled=True,
# tls_cert_path="/etc/ssl/server.crt",
# tls_key_path="/etc/ssl/server.key",
)Mutual TLS (mTLS) Example
# Server with client certificate verification
tls = TLSConfig(
enabled=True,
cert_path="/etc/ssl/server.crt",
key_path="/etc/ssl/server.key",
ca_cert_path="/etc/ssl/ca.crt", # Verify client certs
require_client_cert=True, # Require client auth
)📡 ClientChannelConfig
Configuration for gRPC client channels. Use this instead of hardcoded values.
from django_cfg.modules.django_grpc.configs import ClientChannelConfig| Field | Type | Default | Description |
|---|---|---|---|
address | str | required | Server address (host:port) |
use_tls | bool | False | Use TLS connection |
connect_timeout | float | 3.0 | Connection timeout (seconds) |
call_timeout | float | 5.0 | Default RPC timeout (seconds) |
keepalive_time_ms | int | 30000 | Keepalive ping interval |
keepalive_timeout_ms | int | 10000 | Keepalive timeout |
max_retries | int | 3 | Max retry attempts |
enable_retries | bool | True | Enable automatic retries |
max_send_message_length | int | 4MB | Max outbound message size |
max_receive_message_length | int | 4MB | Max inbound message size |
Example
from django_cfg.modules.django_grpc.configs import ClientChannelConfig, TLSConfig
from django_cfg.modules.django_grpc.services.client import DynamicGRPCClient
# Create config
config = ClientChannelConfig(
address="grpc.example.com:443",
use_tls=True,
max_retries=5,
call_timeout=30.0,
)
# Create client with config
client = DynamicGRPCClient(config=config)🔁 Resilience Configuration
Production-grade retry, circuit breaker, and structured logging for gRPC operations.
RetryConfig
from django_cfg.modules.django_grpc.resilience import RetryConfig
retry = RetryConfig(
enabled=True,
attempts=5,
timeout=30.0,
wait_initial=0.1,
wait_max=10.0,
wait_jitter=0.1,
)| Field | Type | Default | Description |
|---|---|---|---|
enabled | bool | True | Enable automatic retry |
attempts | int | 5 | Maximum retry attempts (1-20) |
timeout | float | 30.0 | Total timeout in seconds (1-300) |
wait_initial | float | 0.1 | Initial backoff in seconds (0.01-10) |
wait_max | float | 10.0 | Maximum backoff in seconds (1-60) |
wait_jitter | float | 0.1 | Jitter factor (0.0-1.0) |
CircuitBreakerConfig
from django_cfg.modules.django_grpc.resilience import CircuitBreakerConfig
circuit_breaker = CircuitBreakerConfig(
enabled=True,
fail_max=5,
reset_timeout=60.0,
success_threshold=2,
)| Field | Type | Default | Description |
|---|---|---|---|
enabled | bool | True | Enable circuit breaker |
fail_max | int | 5 | Failures before circuit opens (1-100) |
reset_timeout | float | 60.0 | Seconds before half-open state (1-3600) |
success_threshold | int | 2 | Successes required to close circuit (1-10) |
LoggingConfig
from django_cfg.modules.django_grpc.resilience import LoggingConfig
logging_config = LoggingConfig(
enabled=True,
json_output=True,
log_level="INFO",
)| Field | Type | Default | Description |
|---|---|---|---|
enabled | bool | True | Enable structured logging |
json_output | bool | True | JSON format (False = console) |
log_level | str | ”INFO” | Minimum log level |
Combined ResilienceConfig
from django_cfg.modules.django_grpc.resilience import ResilienceConfig
config = ResilienceConfig(
retry=RetryConfig(attempts=5),
circuit_breaker=CircuitBreakerConfig(fail_max=5),
logging=LoggingConfig(json_output=True),
)Learn more: Resilience Patterns
🏊 Connection Pool Configuration
Efficient channel reuse for high-performance gRPC applications.
PoolConfig
from django_cfg.modules.django_grpc.services.client import PoolConfig
pool_config = PoolConfig(
max_size=20,
idle_timeout=120.0,
min_idle=2,
max_age=3600.0,
cleanup_interval=60.0,
)| Field | Type | Default | Description |
|---|---|---|---|
max_size | int | 20 | Maximum channels in pool (1-100) |
idle_timeout | float | 120.0 | Close idle channels after (10-3600s) |
min_idle | int | 2 | Keep minimum idle channels (0-10) |
max_age | float | 3600.0 | Maximum channel age (60-86400s) |
cleanup_interval | float | 60.0 | Cleanup check interval (10-600s) |
Using Pool with Resilient Client
from django_cfg.modules.django_grpc.services.client import (
AsyncResilientGRPCClient,
PoolConfig,
)
async with AsyncResilientGRPCClient(
host="localhost",
port=50051,
use_pool=True,
pool_config=PoolConfig(max_size=50),
) as client:
result = await client.call_method(...)Learn more: Connection Pooling
🎯 Environment-Specific Configs
Development
from django_cfg import GRPCKeepaliveConfig
class DevelopmentConfig(DjangoConfig):
DEBUG = True
grpc: GRPCConfig = GRPCConfig(
enabled=True,
server=GRPCServerConfig(
host="127.0.0.1", # Localhost only
port=50051,
enable_reflection=True, # Enable for testing
enable_health_check=True,
),
auth=GRPCAuthConfig(
enabled=True, # Enable auth even in dev
require_auth=False,
api_key_header="x-api-key",
accept_django_secret_key=True, # Allow SECRET_KEY for convenience
),
enabled_apps=["apps.users"], # Limited apps
)Production
from django_cfg import GRPCKeepaliveConfig, GRPCConnectionLimitsConfig
class ProductionConfig(DjangoConfig):
DEBUG = False
grpc: GRPCConfig = GRPCConfig(
enabled=True,
server=GRPCServerConfig(
host="[::]", # All interfaces
port=50051,
enable_reflection=False, # Disable in production
enable_health_check=True, # Keep health checks
# Optimized keepalive for streaming
keepalive=GRPCKeepaliveConfig.for_streaming(),
connection_limits=GRPCConnectionLimitsConfig(
max_connection_idle_ms=7200000, # 2 hours
),
),
auth=GRPCAuthConfig(
enabled=True, # Enable auth
require_auth=True, # Require by default
# API key configuration
api_key_header="x-api-key",
accept_django_secret_key=False, # Disable SECRET_KEY in production
public_methods=[
"/grpc.health.v1.Health/Check",
],
),
enabled_apps=[
"apps.users",
"apps.products",
"apps.orders",
"apps.payments",
],
)Testing
class TestingConfig(DjangoConfig):
TESTING = True
grpc: GRPCConfig = GRPCConfig(
enabled=True,
server=GRPCServerConfig(
host="127.0.0.1",
port=50052, # Different port
enable_reflection=True,
enable_health_check=False, # Not needed in tests
),
auth=GRPCAuthConfig(
enabled=False, # Simplify testing
),
)🌍 Environment Variables
The gRPC configs package supports environment variables out of the box via configs/constants.py:
Core Network Settings
GRPC_HOST=localhost # Default gRPC host
GRPC_PORT=50051 # Default gRPC portTimeout Settings (seconds)
GRPC_RPC_CALL_TIMEOUT=5.0 # RPC call timeout
GRPC_CONNECT_TIMEOUT=3.0 # Connection timeout
GRPC_CHANNEL_READY_TIMEOUT=5.0 # Channel ready timeout
GRPC_QUEUE_TIMEOUT=10.0 # Queue timeout
GRPC_ROUTING_TIMEOUT=5.0 # Cross-process routing timeoutKeepalive Settings (milliseconds)
GRPC_KEEPALIVE_TIME_MS=30000 # Ping interval (30s)
GRPC_KEEPALIVE_TIMEOUT_MS=10000 # Ping timeout (10s)
GRPC_MAX_CONNECTION_IDLE_MS=7200000 # Max idle (2h)Retry & Limits
GRPC_MAX_RETRIES=3 # Max retry attempts
GRPC_MAX_MESSAGE_LENGTH=4194304 # 4MB message limit
GRPC_QUEUE_SIZE=1000 # Command queue sizeCircuit Breaker
GRPC_CB_THRESHOLD=5 # Error threshold
GRPC_CB_TIMEOUT=60.0 # Recovery timeoutLegacy Config Override
You can still override in GRPCConfig:
import os
grpc: GRPCConfig = GRPCConfig(
enabled=os.getenv("GRPC_ENABLED", "true").lower() == "true",
server=GRPCServerConfig(
host=os.getenv("GRPC_HOST", "[::]"),
port=int(os.getenv("GRPC_PORT", "50051")),
enable_reflection=os.getenv("GRPC_ENABLE_REFLECTION", "true").lower() == "true",
),
auth=GRPCAuthConfig(
enabled=os.getenv("GRPC_AUTH_ENABLED", "false").lower() == "true",
require_auth=os.getenv("GRPC_REQUIRE_AUTH", "false").lower() == "true",
api_key_header=os.getenv("GRPC_API_KEY_HEADER", "x-api-key"),
accept_django_secret_key=os.getenv("GRPC_ACCEPT_SECRET_KEY", "true").lower() == "true",
),
)📊 Service Discovery
Auto-Discovery Locations
Services are discovered from these locations (in order):
app/grpc_services.pyapp/grpc_handlers.pyapp/services/grpc.pyapp/handlers/grpc.pyapp/api/grpc.py
Enabled Apps
grpc: GRPCConfig = GRPCConfig(
auto_register_apps=True,
enabled_apps=[
# Full app paths
"apps.users",
"apps.products",
# Core Django apps (if they have gRPC services)
"django.contrib.auth",
# Third-party apps
"mylib.grpc_app",
],
)Manual Registration
If auto-discovery doesn’t work, register manually:
# api/grpc_handlers.py
def register_handlers(server):
from apps.users.grpc_services import UserService
from apps.users import user_pb2_grpc
user_pb2_grpc.add_UserServiceServicer_to_server(
UserService(),
server
)Then in config:
grpc: GRPCConfig = GRPCConfig(
handlers_hook="api.grpc_handlers.register_handlers",
)🚀 Command-Line Options
Override config when starting server:
# Custom host and port
python manage.py rungrpc --host 0.0.0.0 --port 50052
# Verbose output
python manage.py rungrpc --verbosity 3
# Combined
python manage.py rungrpc \
--host 0.0.0.0 \
--port 50052 \
--verbosity 2Streaming Configuration
For bidirectional streaming services, use BidirectionalStreamingConfig:
from django_cfg.modules.django_grpc.services.streaming.config import (
BidirectionalStreamingConfig,
StreamingMode,
PingStrategy,
)
BotStreamingConfig = BidirectionalStreamingConfig(
# Streaming mode
streaming_mode=StreamingMode.ANEXT, # Recommended for long-running streams
# Ping/keepalive for liveness detection
ping_strategy=PingStrategy.INTERVAL,
ping_interval=5.0, # Send PING every 5 seconds
ping_timeout=180.0, # Disconnect if no PONG in 180 seconds
# CRITICAL: Must be None!
connection_timeout=None, # See warning below
# Queue configuration
max_queue_size=1000,
# Async optimizations
enable_sleep_zero=True,
# Logging
enable_logging=True,
logger_name="grpc_streaming",
# Centrifugo integration (optional)
enable_centrifugo=True,
centrifugo_channel_prefix="bot",
centrifugo_auto_publish_messages=True,
centrifugo_auto_publish_commands=True,
)Streaming Configuration Options
| Option | Type | Default | Description |
|---|---|---|---|
streaming_mode | StreamingMode | ANEXT | How to read from input stream |
ping_strategy | PingStrategy | INTERVAL | When to send ping messages |
ping_interval | float | 5.0 | Seconds between pings |
ping_timeout | float | 180.0 | Seconds to wait for pong before disconnect |
connection_timeout | float | None | None | Must be None! |
max_queue_size | int | 1000 | Max pending commands in queue |
enable_sleep_zero | bool | True | Yield to event loop after messages |
enable_logging | bool | True | Enable streaming debug logs |
enable_centrifugo | bool | False | Auto-publish to Centrifugo |
Critical: Never set connection_timeout!
Setting connection_timeout causes premature StopAsyncIteration in grpcio 1.76.0+. Always use connection_timeout=None and rely on ping/keepalive for liveness detection.
See Troubleshooting for details.
Streaming Modes
| Mode | Description | Use Case |
|---|---|---|
ANEXT | Uses await anext() with explicit control | Long-running clients, idle periods |
ASYNC_FOR | Uses async for iteration | High-throughput short-lived streams |
Ping Strategies
| Strategy | Behavior |
|---|---|
DISABLED | No pings (testing only) |
INTERVAL | Send ping every N seconds |
ON_IDLE | Send ping only when no messages for N seconds |
Learn more: Streaming Patterns
Advanced Configuration
Custom Interceptors
Interceptor Order Matters!
Interceptors execute in the order listed. Authentication interceptors MUST come first to set context.user and context.api_key before logging interceptors use them.
Correct order:
ApiKeyAuthInterceptor- Sets context.api_key and context.userRequestLoggerInterceptor- Logs request with api_key infoLoggingInterceptor(dev mode)MetricsInterceptor(dev mode)- Custom interceptors
Wrong order causes: API keys not tracked in logs, user info missing.
# In your config or settings
GRPC_INTERCEPTORS = [
# 1. Auth FIRST (sets context.api_key and context.user)
'django_cfg.modules.django_grpc.auth.ApiKeyAuthInterceptor',
# 2. Request logger (uses context.api_key from auth)
'django_cfg.modules.django_grpc.interceptors.RequestLoggerInterceptor',
# 3. Your custom interceptors
'myapp.interceptors.CustomInterceptor',
]Connection Timeouts
# Client-side (in proto definition or client config)
# For long-running operations
deadline = 300 # 5 minutes
# Server-side (in service)
context.set_deadline(time.time() + 300)Request Size Limits
# In server options
options = [
('grpc.max_send_message_length', 50 * 1024 * 1024), # 50MB
('grpc.max_receive_message_length', 50 * 1024 * 1024), # 50MB
]
server = grpc.server(
futures.ThreadPoolExecutor(max_workers=10),
interceptors=interceptors,
options=options,
)📚 Configuration Checklist
Development ✅
-
enabled=True -
host="127.0.0.1"(localhost) -
enable_reflection=True(for grpcurl) -
auth.enabled=False(easy testing)
Production ✅
-
enabled=True -
host="[::]"(all interfaces) -
enable_reflection=False(security) -
auth.enabled=True(security) -
auth.require_auth=True(strict) -
keepalive=GRPCKeepaliveConfig.for_streaming()(streaming) - Environment variables for secrets
- Health check enabled
- Monitoring/logging enabled
DjangoGrpcModuleConfig — Top-Level Fields
The actual top-level configuration class is DjangoGrpcModuleConfig (defined in __cfg__.py). It is the single source of truth that composes all sub-configs.
from django_cfg.modules.django_grpc.__cfg__ import DjangoGrpcModuleConfig
from django_cfg.modules.django_grpc.config.server import GrpcServerConfig
from django_cfg.modules.django_grpc.config.auth import GrpcAuthConfig
from django_cfg.modules.django_grpc.config.resilience import ResilienceConfig
from django_cfg.modules.django_grpc.config.pool import GrpcPoolConfig
from django_cfg.modules.django_grpc.config.metrics import MetricsConfig
from django_cfg.modules.django_grpc.config.observability import ObservabilityConfig
grpc_module = DjangoGrpcModuleConfig(
enabled=True,
public_url="grpc.example.com:443",
server=GrpcServerConfig(host="[::]", port=50051),
auth=GrpcAuthConfig(require_auth=True),
resilience=ResilienceConfig(),
pool=GrpcPoolConfig(),
metrics=MetricsConfig(),
observability=ObservabilityConfig(),
)| Field | Type | Default | Description |
|---|---|---|---|
enabled | bool | True | Enable the gRPC module |
server | GrpcServerConfig | defaults | Server bind and limits |
public_url | str | None | None | Public gRPC URL for external clients |
internal_url | str | None | None | Internal container-to-container URL |
handlers_hook | str | list[str] | "" | Import path(s) to a grpc_handlers function for manual service registration |
enabled_apps | list[str] | [] | Django apps to expose via gRPC (auto-discovery) |
package_prefix | str | "api" | Proto package prefix |
auth | GrpcAuthConfig | defaults | Authentication settings |
resilience | ResilienceConfig | defaults | Retry and circuit breaker |
pool | GrpcPoolConfig | defaults | Connection pool |
persistence | GrpcPersistenceConfig | defaults | D1/database persistence |
observability | ObservabilityConfig | defaults | Centrifugo publishing, Telegram alerts, OpenTelemetry |
metrics | MetricsConfig | defaults | In-memory metrics and Prometheus export |
GrpcServerConfig
| Field | Type | Default | Description |
|---|---|---|---|
host | str | "[::]" | IPv4/IPv6 listen address |
port | int | 50051 | Listen port (1–65535) |
max_workers | int | 10 | Thread pool workers (1–256) |
max_send_message_length | int | 4194304 | Max outbound message bytes (4 MB) |
max_receive_message_length | int | 4194304 | Max inbound message bytes (4 MB) |
enable_reflection | bool | False | Enable server reflection (grpcurl). Disable in production — exposes the full schema publicly. |
enable_health_check | bool | True | Enable grpc.health.v1.Health service |
shutdown_grace_seconds | float | 5.0 | Graceful shutdown wait time (0–60 s) |
keepalive | GrpcKeepaliveConfig | defaults | HTTP/2 keepalive and connection lifetime |
tls | TLSConfig | None | None | Server TLS. When None, binds an insecure port. |
reflection_require_auth | bool | False | Gate reflection behind JWT auth |
reflection_admin_key | str | None | None | Bypass reflection auth via x-admin-key metadata (dev tooling) |
enable_h3 | bool | False | HTTP/3 (QUIC) frontend via Hypercorn. Requires pip install django-cfg[grpc-h3]. |
h3_host | str | "0.0.0.0" | HTTP/3 listen address (only when enable_h3=True) |
h3_port | int | 50052 | HTTP/3 listen port (only when enable_h3=True) |
GrpcKeepaliveConfig
Controls HTTP/2 PING frames and connection lifetime on the server side.
| Field | Type | Default | Description |
|---|---|---|---|
time_ms | int | 30000 | Keepalive ping interval (ms) |
timeout_ms | int | 10000 | Time to wait for a PING ACK before closing (ms) |
permit_without_calls | bool | True | Allow pings even with no active RPCs |
max_pings_without_data | int | 0 | Max pings without data frames. 0 = unlimited |
http2_min_ping_interval_ms | int | 5000 | Minimum time between HTTP/2 pings (ms) |
max_connection_idle_ms | int | 600000 | Close idle connections after N ms. 0 = disabled (10 min default) |
max_connection_age_ms | int | 3600000 | Maximum connection lifetime (ms). 0 = disabled (1 h default) |
max_connection_age_grace_ms | int | 60000 | Grace period after max_connection_age_ms before forced close (1 min default) |
GrpcPoolConfig
Unified connection pool (single source of truth, replacing older per-file PoolConfig classes).
from django_cfg.modules.django_grpc.config.pool import GrpcPoolConfig
pool = GrpcPoolConfig(
enabled=True,
max_size=20,
idle_timeout=120.0,
min_idle=2,
max_age=3600.0,
cleanup_interval=60.0,
health_check_interval=30.0,
channel_ready_timeout=5.0,
)| Field | Type | Default | Description |
|---|---|---|---|
enabled | bool | True | Enable connection pooling |
max_size | int | 20 | Maximum channels in pool (1–200) |
idle_timeout | float | 120.0 | Seconds before an idle channel is closed (10–3600) |
min_idle | int | 2 | Minimum idle channels to maintain per address (0–20) |
max_age | float | 3600.0 | Maximum channel lifetime in seconds (60–86400) |
cleanup_interval | float | 60.0 | Seconds between pool cleanup cycles (10–600) |
health_check_interval | float | 30.0 | Seconds between idle channel health checks (5–600) |
channel_ready_timeout | float | 5.0 | Seconds to wait for a channel to become ready (1–60) |
See Connection Pooling for detailed usage.
MetricsConfig
Controls in-memory request metrics collection and optional Prometheus export.
from django_cfg.modules.django_grpc.config.metrics import MetricsConfig
metrics = MetricsConfig(
enabled=True,
response_time_ttl=3600.0,
prometheus_enabled=False,
)| Field | Type | Default | Description |
|---|---|---|---|
enabled | bool | True | Enable in-memory metrics collection |
response_time_ttl | float | 3600.0 | TTL in seconds for in-memory response time history (60–86400). Prevents unbounded growth. |
prometheus_enabled | bool | False | Export metrics via prometheus_client (requires the prometheus_client package). When enabled, exposes standard gRPC Prometheus counters and histograms. |
When prometheus_enabled=True and prometheus_client is installed, the following metrics are exported with labels {grpc_service, grpc_method, grpc_type}:
| Metric | Type | Description |
|---|---|---|
grpc_server_started_total | Counter | Total started RPCs |
grpc_server_handled_total | Counter | Total finished RPCs (adds grpc_code label) |
grpc_server_handling_seconds | Histogram | RPC latency |
grpc_server_msg_received_total | Counter | Streaming messages received |
grpc_server_msg_sent_total | Counter | Streaming messages sent |
ObservabilityConfig
Controls Centrifugo real-time publishing, Telegram error notifications, and OpenTelemetry tracing.
from django_cfg.modules.django_grpc.config.observability import ObservabilityConfig
observability = ObservabilityConfig(
otel_enabled=False,
)| Field | Type | Default | Description |
|---|---|---|---|
centrifugo | CentrifugoPublishConfig | defaults | Centrifugo event publishing settings |
telegram | TelegramNotifyConfig | defaults | Telegram notification settings |
otel_enabled | bool | False | Prepend OpenTelemetryServerInterceptor (requires opentelemetry-instrumentation-grpc). Interceptor order: OTel → ErrorHandling → Auth → Observability. |
CentrifugoPublishConfig
| Field | Type | Default | Description |
|---|---|---|---|
enabled | bool | True | Enable Centrifugo event publishing |
publish_start | bool | False | Publish rpc_start events (high volume — disabled by default) |
publish_end | bool | True | Publish rpc_end events |
publish_errors | bool | True | Publish error events |
publish_stream_messages | bool | False | Publish per-message stream events (very high volume — disabled by default) |
channel_template | str | "grpc:{service}:{method}:meta" | Centrifugo channel pattern for method events |
error_channel_template | str | "grpc:{service}:{method}:errors" | Centrifugo channel pattern for error events |
max_retries | int | 3 | Publish retry attempts on transient failure (0–10) |
max_concurrent_publishes | int | 100 | Semaphore cap on concurrent fire-and-forget publish tasks (1–10000) |
TelegramNotifyConfig
| Field | Type | Default | Description |
|---|---|---|---|
enabled | bool | False | Send gRPC error/event notifications to Telegram |
exclude_methods | list[str] | Health/reflection paths | Method paths excluded from notifications |
Default excluded methods: /grpc.health.v1.Health/Check, /grpc.health.v1.Health/Watch, /grpc.reflection.v1alpha.ServerReflection/ServerReflectionInfo.
Related Documentation
- Getting Started - Build your first service
- TLS Configuration - Server TLS, client TLS, mTLS
- Resilience Patterns - Retry, circuit breaker, logging
- Connection Pooling - Channel reuse
- Betterproto2 - Modern Python gRPC
- Streaming Patterns - Bidirectional streaming configuration
- Troubleshooting - Common issues and solutions
- Authentication - API keys authentication
- FAQ - Common questions
Configuration Tip: Start with defaults, measure performance, then tune based on actual traffic patterns. For streaming, always use connection_timeout=None.