{"id":44150449,"url":"https://github.com/lbliii/pounce","last_synced_at":"2026-05-23T18:01:36.724Z","repository":{"id":337091668,"uuid":"1152291289","full_name":"lbliii/pounce","owner":"lbliii","description":"=^..^= Pounce — Free-threading-native ASGI server for Python 3.14+ with real thread parallelism and streaming-first I/O","archived":false,"fork":false,"pushed_at":"2026-05-22T15:56:06.000Z","size":1514,"stargazers_count":1,"open_issues_count":2,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-22T17:52:37.480Z","etag":null,"topics":["asgi","async","cpython","free-threading","http","nogil","python","quic","sans-io","server","threads"],"latest_commit_sha":null,"homepage":"https://lbliii.github.io/pounce/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lbliii.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":"ROADMAP.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":".github/AGENTS.md","dco":null,"cla":null}},"created_at":"2026-02-07T16:56:27.000Z","updated_at":"2026-05-22T15:56:08.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/lbliii/pounce","commit_stats":null,"previous_names":["lbliii/pounce"],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/lbliii/pounce","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lbliii%2Fpounce","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lbliii%2Fpounce/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lbliii%2Fpounce/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lbliii%2Fpounce/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lbliii","download_url":"https://codeload.github.com/lbliii/pounce/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lbliii%2Fpounce/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33406444,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-23T04:15:53.637Z","status":"ssl_error","status_checked_at":"2026-05-23T04:15:53.242Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["asgi","async","cpython","free-threading","http","nogil","python","quic","sans-io","server","threads"],"created_at":"2026-02-09T03:15:29.737Z","updated_at":"2026-05-23T18:01:36.718Z","avatar_url":"https://github.com/lbliii.png","language":"Python","funding_links":[],"categories":["Http servers"],"sub_categories":["More"],"readme":"# =^..^= Pounce\n\n[![PyPI version](https://img.shields.io/pypi/v/bengal-pounce.svg)](https://pypi.org/project/bengal-pounce/)\n[![Build Status](https://github.com/lbliii/pounce/actions/workflows/ci.yml/badge.svg)](https://github.com/lbliii/pounce/actions/workflows/ci.yml)\n[![Python 3.14+](https://img.shields.io/badge/python-3.14+-blue.svg)](https://pypi.org/project/bengal-pounce/)\n[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)\n[![Status: Beta](https://img.shields.io/badge/status-beta-yellow.svg)](https://pypi.org/project/bengal-pounce/)\n\n**Pure Python ASGI server for Python 3.14t, with a frozen config model and a low-overhead HTTP/1.1 fast path.**\n\n```python\nimport pounce\n\npounce.run(\"myapp:app\")\n```\n\n---\n\n## What is Pounce?\n\nPounce is a Python ASGI server for Python 3.14+, with a worker model designed for\nfree-threaded Python 3.14t. It runs standard ASGI applications, supports streaming\nresponses, and gives you a clear upgrade path from process-based servers such as\nUvicorn.\n\nPounce's built-in HTTP/1.1 parser is optimized for the sync worker hot path, its\n`ServerConfig` object is frozen after construction, and thread-worker reloads\nuse generational worker swaps with drain behavior.\n\nOn Python 3.14t, worker threads share one interpreter and one copy of your app. On GIL\nbuilds, Pounce falls back to multi-process workers automatically.\n\n**Why people pick it:**\n\n- **ASGI-first** — Runs standard ASGI apps with CLI and programmatic entry points\n- **Free-threading native** — True thread parallelism with a frozen shared `ServerConfig`\n- **Fast-path parsing** — Built-in HTTP/1.1 parser for sync workers with tested smuggling and header-limit checks\n- **Protocol extras** — HTTP/2 and WebSocket are install-gated optional paths; HTTP/3 is optional with limited parity\n- **Thread-worker reloads** — Rolling restart uses generational worker swap with drain behavior on supported worker modes\n- **Observable surfaces** — Typed lifecycle events, optional Prometheus metrics, OpenTelemetry, and Server-Timing headers\n- **Optional helpers** — TLS, compression, static files, middleware, rate limiting, and request queueing stay opt-in\n- **Migration path** — Familiar CLI for teams moving from Uvicorn-style deployments\n\nSee [docs/design/core-contract.md](docs/design/core-contract.md) for the supported core,\noptional helpers, and proof required for public claims.\n\n## Use Pounce For\n\n- **Serving ASGI apps** — Tunable workers, TLS, graceful shutdown, and deployment controls\n- **Free-threaded Python deployments** — Shared-memory worker threads on Python 3.14t\n- **Streaming workloads** — Server-sent events, streamed HTML, and token-by-token responses\n- **Teams migrating from Uvicorn** — Similar CLI shape with a different worker model\n\n---\n\n## Framework Compatibility\n\nTested in CI with 48 integration tests across every major ASGI framework:\n\n| Framework | Status | Features Verified |\n|-----------|--------|-------------------|\n| **FastAPI** 0.135+ | Full | Routing, Pydantic validation, dependency injection, middleware, exception handlers, lifespan, WebSocket, streaming, OpenAPI schema |\n| **Starlette** 1.0+ | Full | Routing, BaseHTTPMiddleware, lifespan with state, streaming, WebSocket, background tasks, exception handlers |\n| **Django** 6.0+ | Full | Async views, URL routing, path params, JSON body, query params, middleware, error handling |\n| **Litestar** 2.21+ | Core | Routing, dependency injection, middleware, lifespan, streaming, exception handlers. WebSocket: known routing issue |\n\nPounce achieves compatibility through correct ASGI 3.0 implementation — no framework-specific code or workarounds.\n\n---\n\n## Performance\n\nPounce is designed to make the pure-Python request path competitive while keeping\nthe server core free of C extensions. Treat the numbers below as a benchmark\nsnapshot, not a universal guarantee.\n\n| Scenario | Pounce | Uvicorn | Notes |\n|----------|--------|---------|-------|\n| 1 worker | ~7.2k req/s | ~6.5k req/s | Async event loop, h11 parser |\n| 4 workers | ~16k req/s | ~17k req/s | Threads (pounce) vs processes (uvicorn) |\n\n*Measured with `wrk -t4 -c100 -d10s` on macOS Apple Silicon, plain-text \"hello world\" ASGI app, Python 3.14t. Re-run locally before making deployment decisions.*\n\nRun `pounce bench --workers 4 --compare` to reproduce on your machine.\nFor release or PR evidence, use\n`python benchmarks/run_benchmark.py --repeat 5 --artifact-output results.json`\nso the run carries the metadata required by `benchmarks/artifact-schema.json`\nand grouped variance across samples.\n\nKey optimizations in the sync worker path:\n- **Fast HTTP/1.1 parser** — Direct bytes parsing is benchmarked separately from h11 and covers method validation, header size limits, duplicate `Content-Length`, and `Content-Length`/`Transfer-Encoding` ambiguity\n- **Keep-alive connections** — Connection reuse eliminates TCP handshake overhead\n- **Shared socket distribution** — Single accept queue for thread workers avoids macOS SO_REUSEPORT limitations\n\n---\n\n## Installation\n\n```bash\npip install bengal-pounce\n```\n\nRequires Python 3.14+\n\n**Optional extras:**\n\n```bash\npip install bengal-pounce[h2]     # HTTP/2 stream multiplexing\npip install bengal-pounce[ws]     # WebSocket via wsproto\npip install bengal-pounce[tls]    # TLS with truststore\npip install bengal-pounce[h3]     # HTTP/3 (QUIC/UDP, requires TLS; limited parity)\npip install bengal-pounce[full]   # All protocol extras\n```\n\n---\n\n## Quick Start\n\n| Usage | Command |\n|-------|---------|\n| **Programmatic** | `pounce.run(\"myapp:app\")` |\n| **CLI** | `pounce myapp:app` |\n| **Multi-worker** | `pounce myapp:app --workers 4` |\n| **TLS** | `pounce myapp:app --ssl-certfile cert.pem --ssl-keyfile key.pem` |\n| **HTTP/3** | `pounce myapp:app --http3 --ssl-certfile cert.pem --ssl-keyfile key.pem` |\n| **Dev reload** | `pounce myapp:app --reload` |\n| **App factory** | `pounce myapp:create_app()` |\n| **Testing** | `with TestServer(app) as server: ...` |\n\n---\n\n## Features\n\n| Feature | Description | Docs |\n|---------|-------------|------|\n| **Deployment** | Production workers, compression, observability, and shutdown behavior | [Deployment →](https://lbliii.github.io/pounce/docs/deployment/) |\n| **Migration** | Move from Uvicorn with similar CLI concepts | [Migrate from Uvicorn →](https://lbliii.github.io/pounce/docs/tutorials/migrate-from-uvicorn/) |\n| **HTTP/1.1** | h11 (async) + fast built-in parser (sync) | [HTTP/1.1 →](https://lbliii.github.io/pounce/docs/protocols/http1/) |\n| **HTTP/2** | Optional stream multiplexing via h2 | [HTTP/2 →](https://lbliii.github.io/pounce/docs/protocols/http2/) |\n| **HTTP/3** | Optional QUIC/UDP via bengal-zoomies; limited parity until reload/drain and benchmark proof lands | [HTTP/3 →](https://lbliii.github.io/pounce/docs/protocols/http3/) |\n| **WebSocket** | Optional RFC 6455 support via wsproto; WS-over-H2 requires h2 + ws extras | [WebSocket →](https://lbliii.github.io/pounce/docs/protocols/websocket/) |\n| **Static Files** | Pre-compressed files, ETags, range requests | [Static Files →](https://lbliii.github.io/pounce/docs/features/static-files/) |\n| **Middleware** | ASGI3 middleware stack support | [Middleware →](https://lbliii.github.io/pounce/docs/features/middleware/) |\n| **OpenTelemetry** | Optional distributed tracing (OTLP) | [OpenTelemetry →](https://lbliii.github.io/pounce/docs/deployment/observability/) |\n| **Lifecycle Logging** | Structured JSON event logging | [Logging →](https://lbliii.github.io/pounce/docs/features/lifecycle-logging/) |\n| **Graceful Shutdown** | Mode-scoped connection draining for deploys | [Shutdown →](https://lbliii.github.io/pounce/docs/deployment/lifecycle/) |\n| **Dev Error Pages** | Rich tracebacks with syntax highlighting | [Errors →](https://lbliii.github.io/pounce/docs/features/error-pages/) |\n| **TLS** | SSL with truststore integration | [TLS →](https://lbliii.github.io/pounce/docs/configuration/tls/) |\n| **Compression** | zstd (stdlib PEP 784) + gzip + WS compression | [Compression →](https://lbliii.github.io/pounce/docs/deployment/compression/) |\n| **Workers** | Auto-detect: threads (3.14t) or processes (GIL) | [Workers →](https://lbliii.github.io/pounce/docs/deployment/workers/) |\n| **Auto Reload** | Graceful restart on file changes | [Reload →](https://lbliii.github.io/pounce/docs/deployment/lifecycle/) |\n| **Rate Limiting** | Optional per-IP token bucket with 429 responses | [Rate Limiting →](https://lbliii.github.io/pounce/docs/deployment/backpressure/) |\n| **Request Queueing** | Optional bounded queue with 503 load shedding | [Request Queueing →](https://lbliii.github.io/pounce/docs/deployment/backpressure/) |\n| **Prometheus** | Optional `/metrics` endpoint | [Metrics →](https://lbliii.github.io/pounce/docs/deployment/observability/) |\n| **Sentry** | Optional error tracking and performance monitoring | [Sentry →](https://lbliii.github.io/pounce/docs/deployment/observability/) |\n| **Testing** | `TestServer` + pytest fixture for integration tests | [Testing →](https://lbliii.github.io/pounce/docs/testing/) |\n| **Benchmarking** | Built-in `pounce bench` command with comparative analysis | [Bench →](https://lbliii.github.io/pounce/docs/features/) |\n| **Lifecycle Events** | Public API for typed connection/request events | [API →](https://lbliii.github.io/pounce/docs/reference/api/) |\n\n📚 **Full documentation**: [lbliii.github.io/pounce](https://lbliii.github.io/pounce/) | **[Complete Feature List →](https://lbliii.github.io/pounce/docs/features/)**\n\n---\n\n## Usage\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eProgrammatic Configuration\u003c/strong\u003e — Full control from Python\u003c/summary\u003e\n\n```python\nimport pounce\n\npounce.run(\n    \"myapp:app\",\n    host=\"0.0.0.0\",\n    port=8000,\n    workers=4,\n)\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eHow It Works\u003c/strong\u003e — Adaptive worker model\u003c/summary\u003e\n\nOn **Python 3.14t** (free-threading): workers are threads. One process, N threads, each with\nits own asyncio event loop. Shared memory, no fork overhead, no IPC.\n\nOn **GIL builds**: workers are processes. Same API, same config. The supervisor detects the\nruntime via `sys._is_gil_enabled()` and adapts automatically.\n\nA request flows through: socket accept -\u003e protocol parser -\u003e ASGI scope\nconstruction -\u003e `app(scope, receive, send)` -\u003e response serialization -\u003e socket write.\nAsync workers use h11; sync workers use a fast built-in parser for lower latency.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eProtocol Extras\u003c/strong\u003e — Install only what you need\u003c/summary\u003e\n\n| Protocol | Backend | Install |\n|----------|---------|---------|\n| HTTP/1.1 | h11 (async) / fast built-in parser (sync) | built-in |\n| HTTP/2 | h2 (stream multiplexing, priority signals) | `bengal-pounce[h2]` |\n| WebSocket | wsproto (HTTP/1 WebSocket; WS-over-H2 also requires h2) | `bengal-pounce[ws]` |\n| TLS | stdlib ssl + truststore | `bengal-pounce[tls]` |\n| HTTP/3 | bengal-zoomies (QUIC/UDP) | `bengal-pounce[h3]` |\n| All | Everything above | `bengal-pounce[full]` |\n\nCompression uses Python 3.14's stdlib `compression.zstd` — zero external dependencies.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eTesting\u003c/strong\u003e — Real server for integration tests\u003c/summary\u003e\n\n```python\nfrom pounce.testing import TestServer\nimport httpx\n\ndef test_homepage(my_app):\n    with TestServer(my_app) as server:\n        resp = httpx.get(f\"{server.url}/\")\n        assert resp.status_code == 200\n```\n\nThe `pounce_server` pytest fixture is auto-registered when pounce is installed:\n\n```python\ndef test_api(pounce_server, my_app):\n    server = pounce_server(my_app)\n    resp = httpx.get(f\"{server.url}/health\")\n    assert resp.status_code == 200\n```\n\n\u003c/details\u003e\n\n---\n\n## Key Ideas\n\n- **Free-threading first.** Threads, not processes. One interpreter, N event loops, and a\n  frozen shared `ServerConfig`. On GIL builds, falls back to multi-process automatically.\n- **Pure Python.** No Rust, no C extensions in the server core. Debuggable, hackable,\n  readable.\n- **Typed end-to-end.** Frozen config, typed ASGI definitions, and no new type suppressions without review.\n- **One dependency.** `h11` for HTTP/1.1 parsing. Everything else is optional.\n- **Observable by design.** Lifecycle events are public API — `from pounce import BufferedCollector, ResponseCompleted`. Frameworks build dashboards on typed events, not log parsing.\n- **Framework tested.** Verified against FastAPI, Starlette, Django, and Litestar with 48 integration tests.\n- **Optional helpers.** Static files, middleware, rate limiting, request queueing,\n  Prometheus metrics, Sentry, and OpenTelemetry are available without becoming\n  mandatory request-path dependencies.\n\n---\n\n## Documentation\n\n📚 **[lbliii.github.io/pounce](https://lbliii.github.io/pounce/)**\n\n| Section | Description |\n|---------|-------------|\n| [Get Started](https://lbliii.github.io/pounce/docs/get-started/) | Installation and quickstart |\n| [Protocols](https://lbliii.github.io/pounce/docs/protocols/) | HTTP/1.1, HTTP/2, WebSocket, HTTP/3 |\n| [Configuration](https://lbliii.github.io/pounce/docs/configuration/) | Server config, TLS, CLI |\n| [Deployment](https://lbliii.github.io/pounce/docs/deployment/) | Workers, compression, production |\n| [Extending](https://lbliii.github.io/pounce/docs/extending/) | ASGI bridge, custom protocols |\n| [Tutorials](https://lbliii.github.io/pounce/docs/tutorials/) | Uvicorn migration guide |\n| [Troubleshooting](https://lbliii.github.io/pounce/docs/troubleshooting/) | Common issues and fixes |\n| [Reference](https://lbliii.github.io/pounce/docs/reference/) | API documentation |\n| [About](https://lbliii.github.io/pounce/docs/about/) | Architecture, performance, FAQ |\n\n---\n\n## Development\n\n```bash\ngit clone https://github.com/lbliii/pounce.git\ncd pounce\nuv sync --group dev\npytest\n```\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) for setup, feedback loops, and recipes\n(how to add a test, a config field, or an error). Read [AGENTS.md](AGENTS.md)\nfor the project's design philosophy and stop-and-ask escape hatches.\n\n---\n\n## The Bengal Ecosystem\n\nA structured reactive stack — every layer written in pure Python for 3.14t free-threading.\n\n| | | | |\n|--:|---|---|---|\n| **ᓚᘏᗢ** | [Bengal](https://github.com/lbliii/bengal) | Static site generator | [Docs](https://lbliii.github.io/bengal/) |\n| **∿∿** | [Purr](https://github.com/lbliii/purr) | Content runtime | — |\n| **⌁⌁** | [Chirp](https://github.com/lbliii/chirp) | Web framework | [Docs](https://lbliii.github.io/chirp/) |\n| **=^..^=** | **Pounce** | ASGI server ← You are here | [Docs](https://lbliii.github.io/pounce/) |\n| **)彡** | [Kida](https://github.com/lbliii/kida) | Template engine | [Docs](https://lbliii.github.io/kida/) |\n| **ฅᨐฅ** | [Patitas](https://github.com/lbliii/patitas) | Markdown parser | [Docs](https://lbliii.github.io/patitas/) |\n| **⌾⌾⌾** | [Rosettes](https://github.com/lbliii/rosettes) | Syntax highlighter | [Docs](https://lbliii.github.io/rosettes/) |\n\nPython-native. Free-threading ready. No npm required.\n\n---\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flbliii%2Fpounce","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flbliii%2Fpounce","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flbliii%2Fpounce/lists"}