{"id":582,"library":"sse-starlette","title":"SSE-Starlette","description":"sse-starlette is a production-ready Python library that provides a Server-Sent Events (SSE) plugin for Starlette and FastAPI frameworks. It offers a standards-compliant implementation of the W3C SSE specification, including features like automatic client disconnect detection, graceful shutdown, and thread-safe event management. The current version is 3.3.3, and the library maintains an active release cadence with regular updates and dependency management.","status":"active","version":"3.3.3","language":"python","source_language":"en","source_url":"https://github.com/sysid/sse-starlette","tags":["starlette","fastapi","sse","server-sent-events","real-time","async","streaming","web"],"install":[{"cmd":"pip install sse-starlette","lang":"bash","label":"Install stable version"}],"dependencies":[{"reason":"Core web framework dependency for SSE integration.","package":"starlette","optional":false},{"reason":"Asynchronous I/O library used for concurrency management.","package":"anyio","optional":false},{"reason":"Required Python version.","package":"python","optional":false}],"imports":[{"symbol":"EventSourceResponse","correct":"from sse_starlette import EventSourceResponse"},{"symbol":"ServerSentEvent","correct":"from sse_starlette import ServerSentEvent"},{"symbol":"JSONServerSentEvent","correct":"from sse_starlette import JSONServerSentEvent"}],"quickstart":{"code":"import asyncio\nfrom starlette.applications import Starlette\nfrom starlette.routing import Route\nfrom sse_starlette import EventSourceResponse\n\nasync def generate_events():\n    for i in range(10):\n        yield {\"data\": f\"Event {i}\"}\n        await asyncio.sleep(1)\n\nasync def sse_endpoint(request):\n    return EventSourceResponse(generate_events())\n\napp = Starlette(routes=[Route(\"/events\", sse_endpoint)])\n\n# To run this example, you would typically use an ASGI server like uvicorn:\n# uvicorn your_module_name:app --reload\n","lang":"python","description":"This quickstart sets up a basic Starlette application with an `/events` endpoint that streams ten Server-Sent Events, each separated by a one-second delay. The `EventSourceResponse` handles the SSE protocol details, including event formatting and connection management."},"warnings":[{"fix":"Avoid using GZipMiddleware on routes that serve `EventSourceResponse`. Consider configuring your reverse proxy for compression if needed for other endpoints, but bypass it for SSE streams.","message":"SSE streaming does not work in combination with Starlette's GZipMiddleware. Applying GZipMiddleware to an SSE endpoint will buffer the response, preventing real-time delivery.","severity":"gotcha","affected_versions":"<3.3.3"},{"fix":"Configure your reverse proxy to disable buffering for SSE endpoints. For Nginx, add `proxy_buffering off;` and `X-Accel-Buffering: no` header. For other proxies, consult their documentation for equivalent settings.","message":"Reverse proxies (e.g., Nginx, Apache, Cloudflare, Akamai, HAProxy) often buffer responses by default, which can break the real-time nature of SSE. This can cause events to be delayed or batched.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Upgrade to v3.2.0 or newer. Use the `shutdown_event` exposed in generators (v3.3.0+) for cooperative shutdown, or configure `AppStatus.enable_automatic_graceful_drain_mode` to manage how streams terminate during server shutdown. Ensure your graceful shutdown period in `sse-starlette` is less than your ASGI server's graceful shutdown timeout.","message":"Prior to v3.2.0, handling graceful shutdown of SSE streams could be problematic, often leading to 'Waiting for background tasks to complete' warnings or immediate force-cancellation of generators upon server termination. This prevented proper cleanup or sending final events.","severity":"breaking","affected_versions":"<3.2.0"},{"fix":"Upgrade to v3.1.2 or newer to benefit from the fix preventing this task leak.","message":"Versions prior to v3.1.2 had a 'watcher task leak' due to incorrect `threading.local` usage, potentially leading to resource exhaustion or unexpected behavior in long-running applications.","severity":"gotcha","affected_versions":"<3.1.2"},{"fix":"Ensure that any objects passed to SSE generators are thread-safe or are instantiated within the generator's context to prevent concurrent access issues. For database sessions, open and close them within the generator's async scope.","message":"When using database sessions (e.g., SQLAlchemy's `AsyncSession`) or other non-thread-safe objects within SSE generators, care must be taken to avoid passing them directly. The streaming internally uses `anyio.TaskGroups`, which can lead to thread-safety issues.","severity":"gotcha","affected_versions":"All versions"},{"fix":"It is recommended to use a virtual environment for Python projects to avoid permission issues and conflicts with the system package manager. Avoid running pip as the 'root' user. Regularly update pip to its latest version (e.g., `pip install --upgrade pip`).","message":"The test environment generated warnings related to pip usage, specifically concerning running pip as the 'root' user and suggesting a pip version upgrade. These are not direct failures of the tested library but indicate sub-optimal or potentially problematic environment setup for package management.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-05-12T16:20:18.702Z","next_check":"2026-06-26T00:00:00.000Z","problems":[{"fix":"pip install sse-starlette","cause":"The `sse-starlette` library has not been installed in the active Python environment.","error":"ModuleNotFoundError: No module named 'sse_starlette'"},{"fix":"Define an `async def` function that uses `yield` to produce events, then pass this generator function to `EventSourceResponse`.","cause":"`EventSourceResponse` requires an asynchronous generator (an `async def` function that uses `yield`), but a synchronous iterable like a list was provided.","error":"TypeError: 'list' object is not async iterable"},{"fix":"Serialize the data to a JSON string (e.g., using `json.dumps()`) before yielding it from the `async` generator.","cause":"The `async` generator is yielding Python objects (like dictionaries) directly, but `EventSourceResponse` expects event data to be a string or bytes.","error":"TypeError: expected string or bytes-like object, got dict"},{"fix":"Modify the `async` generator to catch `GeneratorExit` and break its loop gracefully, for example, by wrapping the loop in `try...except GeneratorExit: break`.","cause":"The `async` generator function, typically within a `while True` loop, does not properly handle `GeneratorExit` when the client disconnects, leading to the ASGI server reporting an unstopped generator.","error":"RuntimeError: generator didn't stop itself"}],"ecosystem":"pypi","meta_description":null,"install_score":100,"install_tag":"verified","quickstart_score":80,"quickstart_tag":"verified","pypi_latest":"3.4.3","install_checks":{"last_tested":"2026-05-12","tag":"verified","tag_description":"installs cleanly on critical runtimes, fast import, recently tested","results":[{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.21,"mem_mb":7.9,"disk_size":"20.8M"},{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.22,"mem_mb":7.9,"disk_size":"20.8M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":2,"import_time_s":0.16,"mem_mb":7.9,"disk_size":"21M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.15,"mem_mb":7.9,"disk_size":"21M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.36,"mem_mb":8.8,"disk_size":"22.9M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.37,"mem_mb":8.8,"disk_size":"22.9M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":2.2,"import_time_s":0.29,"mem_mb":8.8,"disk_size":"23M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.28,"mem_mb":8.8,"disk_size":"23M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.5,"mem_mb":8.9,"disk_size":"14.6M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.54,"mem_mb":8.9,"disk_size":"14.6M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":1.9,"import_time_s":0.47,"mem_mb":8.9,"disk_size":"15M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.48,"mem_mb":8.9,"disk_size":"15M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.52,"mem_mb":8.8,"disk_size":"14.0M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.52,"mem_mb":8.8,"disk_size":"13.9M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":1.8,"import_time_s":0.46,"mem_mb":8.8,"disk_size":"15M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.47,"mem_mb":8.8,"disk_size":"14M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.22,"mem_mb":7.9,"disk_size":"20.1M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.22,"mem_mb":7.9,"disk_size":"20.2M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":2.3,"import_time_s":0.18,"mem_mb":7.9,"disk_size":"21M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.18,"mem_mb":7.9,"disk_size":"21M"}]},"quickstart_checks":{"last_tested":"2026-04-23","tag":"verified","tag_description":"quickstart runs on critical runtimes, recently tested","results":[{"runtime":"python:3.10-alpine","exit_code":0},{"runtime":"python:3.10-slim","exit_code":0},{"runtime":"python:3.11-alpine","exit_code":0},{"runtime":"python:3.11-slim","exit_code":0},{"runtime":"python:3.12-alpine","exit_code":0},{"runtime":"python:3.12-slim","exit_code":0},{"runtime":"python:3.13-alpine","exit_code":0},{"runtime":"python:3.13-slim","exit_code":0},{"runtime":"python:3.9-alpine","exit_code":0},{"runtime":"python:3.9-slim","exit_code":0}]}}