ServerConfig

The frozen dataclass that controls all server behavior

11 min read 2215 words

Overview

ServerConfig is a frozen dataclass (@dataclass(frozen=True, slots=True)) that holds all server settings. It's created once at startup and shared across workers as frozen server configuration. Treat referenced objects as read-only unless their own API says otherwise.

from pounce import ServerConfig

config = ServerConfig(
    host="0.0.0.0",
    port=8000,
    workers=4,
    compression=True,
    server_timing=True,
    health_check_path="/readyz",
)

Stability Tiers

Not every knob carries the same maturity. Use the tier to decide what to lean on in production. The same classification is surfaced programmatically: pounce config schema stamps an x-stabilityannotation on each beta field.

Tier Meaning
Stable Covered by the core contract. Safe for production; behavior changes follow deprecation policy.
Beta Usable, but the behavior, surface, or proof is still firming up. Pin versions and validate in staging before relying on it.

Stable knobs:host/port/uds, workers/backlog, all worker_mode values (auto/sync/async/subinterpreter), the timeouts (*_timeout), the limits (max_*), and logging (access_log/log_level/log_format).

Beta knobs: rate limiting (rate_limit_*), request queueing (request_queue_*), introspection (introspection_*), HTTP/3 (http3_*), and the observability integrations (otel_*, sentry_*, metrics_*).

Note

Beta is about maturity, not safety: beta knobs are off by default and removable from the request path when disabled. Inspect the live classification with pounce config schema (look for "x-stability": "beta").

Core Fields

Bind Address

Field Type Default Description
host str "127.0.0.1" Bind address
port int 8000 Bind port (0-65535)
uds str | None None Unix domain socket path. Mutually exclusive withhost/port.
uds_permissions int 0o660 File mode applied to created Unix domain sockets.

Workers

Field Type Default Description
workers int 1 Worker count. 0 = auto-detect from CPU cores. 1 = single-worker (no supervisor). 2+ = multi-worker with supervisor.
worker_mode str "auto" With multiple workers,auto resolves to sync threads on 3.14t and async processes on a GIL build. workers=1 uses direct async unless explicit subinterpreter(stable ASGI web-worker path; import path and compatible dependencies required).
worker_startup_failure str "ignore" Worker-hook failure policy:ignore logs and serves for generic ASGI compatibility; shutdown fails boot with POUNCE_WORKER_STARTUP_FAILEDbefore readiness.
backlog int 2048 Socket listen backlog
cpu_affinity bool False Pin each worker to a CPU core (Linux only, reduces cache thrashing)
executor_threads_per_worker int 0 Per-worker thread pool size forasyncio.to_thread(). 0 = auto-size.

Warning

On a GIL build,workers=2+ uses fork. State created during module import, Serverconstruction, or main lifespan startup must be fork-safe. Initialize process-local resources inpounce.worker.startupwith worker_startup_failure="shutdown", or use workers=1. See Workers for the complete contract.

Timeouts

Field Type Default Description
keep_alive_timeout float 5.0 Seconds to keep an idle HTTP connection open between requests
header_timeout float 10.0 Seconds to receive complete request headers (slowloris protection)
request_timeout float 30.0 Maximum seconds to wait for the next request-body event
write_timeout float 30.0 Maximum seconds for blocked HTTP/1.1, HTTP/2, or WebSocket response delivery
startup_timeout float 30.0 Maximum seconds to wait for server startup
shutdown_timeout float 10.0 Seconds per worker join during shutdown (parallel in multi-worker)

Limits

Field Type Default Description
max_request_size int 1,048,576 Maximum request body (1 MB)
max_header_size int 65,536 Maximum total header size (64 KB)
max_headers int 100 Maximum number of headers
max_connections int 10,000 Maximum concurrent connections
max_requests_per_connection int 0 Max requests per keep-alive connection (0 = unlimited)

Logging

Field Type Default Description
access_log bool True Enable access logging
log_level str "info" Log level: debug, info, warning, error, critical
log_format str "auto" Log output format:auto (pretty on TTY, JSON when piped), text, or json
display DisplayConfig | None None Optional startup display configuration.
app_name str | None None App name merged into startup display configuration.
app_tagline str | None None App tagline merged into startup display configuration.
app_version str | None None App version merged into startup display configuration.
signage str | None None Startup signage style override.
access_log_filter Callable[[str, str, int], bool] | None None Optional filter:(method, path, status) -> bool. True = log, False = skip.

HTTP

Field Type Default Description
http2_enabled bool True Advertise h2 via TLS ALPN when the optional dependency is installed; set false to force H1 at a Pounce-owned TLS origin
server_header str "pounce" Value of theServerresponse header
date_header bool True IncludeDateresponse header
root_path str "" ASGI root_path for reverse proxy setups

Compression

Field Type Default Description
compression bool True Enable content-encoding negotiation
compression_min_size int 500 Minimum response size in bytes to compress

Observability

Field Type Default Description
server_timing bool False InjectServer-Timingheader with parse/app/encode durations
health_check_path str | None None Path for the built-in readiness endpoint (recommended:"/readyz"). Returns 503 while draining; disabled by default.
introspection_enabled bool False Enable the built-in/_pounce/infoendpoint.
introspection_bind str "127.0.0.1" Warning-policy bind value for introspection exposure.
introspection_path str "/_pounce/info" Path for the built-in introspection endpoint.

Note

Request IDs are always generated (or extracted from trusted proxies). Every response includes anX-Request-ID header for tracing, and requests from trusted proxies that send X-Request-IDhave their IDs honoured.

Development

Field Type Default Description
debug bool False Enable rich error pages (never use in production)
reload bool False Watch source files and restart workers on changes
reload_include tuple[str, ...] () Extra file extensions to watch beyond the default set (e.g.(".rst", ".scss"))
reload_dirs tuple[str, ...] () Extra directories to watch alongside the current working directory

Whenreload is enabled, the default watch set is .py, .pyi, .yaml, .yml, .toml, .json, .cfg, .ini, .md, .html, .css, .js, .svg. Static-site authoring edits (Markdown, HTML, CSS, JS, SVG) therefore trigger a reload withoutreload_include. The watcher scans the current working directory, everyreload_dirsentry, and the directories behind any configuredstatic_filesmounts; assets stored elsewhere need a matching reload_dirsentry.

Protocol Tuning

Field Type Default Description
h11_max_incomplete_event_size int | None None h11 parser buffer limit (None = h11 default 16 KB)

Security

Field Type Default Description
trusted_hosts frozenset[str] frozenset() Trusted proxy hosts for X-Forwarded-* header validation (empty = strip all proxy headers). Accepts any iterable; normalized to frozenset internally.
forwarded_for_trusted_hops int 1 Number of trusted proxy hops used to select the client address from the right side ofX-Forwarded-For. Must be at least 1.

Note

Whentrusted_hosts is empty, Pounce strips X-Forwarded-For, X-Forwarded-Proto, and X-Forwarded-Host from all requests. Set it to your reverse proxy's IP (e.g. frozenset({"10.0.0.1"})). Trusted X-Forwarded-Host rewrites both scope["server"] and the ASGI Hostheader, including a forwarded port when present. Tuples and lists are also accepted and converted automatically. A wildcard trusts every direct peer and is unsafe on an internet-reachable listener.

X-Real-IP is not used to rewrite scope["client"]; only a trusted peer's X-Forwarded-Forparticipates in Pounce client-address normalization.

TLS

Field Type Default Description
ssl_certfile str | None None Path to TLS certificate file
ssl_keyfile str | None None Path to TLS private key file

Note

ssl_certfile and ssl_keyfile must both be set or both be None. Setting only one raises ValueError.

Extended Fields

These fields control optional features. Most have sensible defaults and don't need to be set for basic usage.

Programmatic Usage

import pounce
from pounce import ServerConfig

# Option 1: Pass kwargs to run()
pounce.run("myapp:app", host="0.0.0.0", workers=4)

# Option 2: Create config explicitly
config = ServerConfig(host="0.0.0.0", workers=4)

Auto-Detect Workers

Whenworkers=0, Pounce calls os.cpu_count()to determine the worker count:

config = ServerConfig(workers=0)
print(config.resolve_workers())  # e.g., 8 on an 8-core machine

See Also