{"id":"bd608c4e-9048-4aad-b81f-94f0387bde5c","shortId":"WGZrAN","kind":"skill","title":"uvicorn","tagline":"Auto-activate for uvicorn imports, uvicorn CLI commands, ASGI server configuration. Uvicorn ASGI server: worker configuration, event loop selection, SSL, lifespan, logging, programmatic API. Produces uvicorn CLI invocations, Config/Server usage, and deployment configurations. Use","description":"# Uvicorn Server Skill\n\nUvicorn is a lightning-fast ASGI server built on uvloop and httptools. It is the community standard for Python ASGI apps and is widely used for development and production deployments.\n\nFor production workloads, consider Granian (see `flow:granian`) — a Rust-based alternative with higher throughput, lower memory use, and native HTTP/2 support.\n\n## Quick Reference\n\n### CLI Usage\n\n```bash\n# Basic ASGI (Litestar, Starlette, FastAPI)\nuvicorn app:main --host 0.0.0.0 --port 8000\n\n# Production: multiple workers\nuvicorn app:main --host 0.0.0.0 --port 8000 --workers 4\n\n# Development: single worker with reload\nuvicorn app:main --host 0.0.0.0 --port 8000 --reload\n```\n\n### Worker Model\n\n```bash\n# Multi-process via uvicorn --workers (uses multiprocessing internally)\nuvicorn app:main --workers 4\n\n# Multi-process via gunicorn + uvicorn worker class (recommended for production)\ngunicorn app:main -k uvicorn.workers.UvicornWorker --workers 4 --bind 0.0.0.0:8000\n```\n\nStarting point formula: `--workers $(( 2 * $(nproc) + 1 ))`\n\n### Event Loop\n\n```bash\n# uvloop (recommended for production — significant throughput gain)\nuvicorn app:main --loop uvloop\n\n# asyncio (default, pure Python fallback)\nuvicorn app:main --loop asyncio\n```\n\n### HTTP Implementation\n\n```bash\n# httptools (faster, C-based — recommended for production)\nuvicorn app:main --http httptools\n\n# h11 (default, pure Python — safer fallback)\nuvicorn app:main --http h11\n```\n\n### SSL Configuration\n\n```bash\nuvicorn app:main \\\n  --host 0.0.0.0 \\\n  --port 8443 \\\n  --ssl-keyfile /etc/ssl/private/app.key \\\n  --ssl-certfile /etc/ssl/certs/app.crt \\\n  --ssl-ca-certs /etc/ssl/certs/ca-bundle.crt\n```\n\n### Lifespan\n\n```bash\n# auto (default — enable if app has lifespan handlers, skip if not)\nuvicorn app:main --lifespan auto\n\n# on — always run startup/shutdown events\nuvicorn app:main --lifespan on\n\n# off — skip lifespan events entirely\nuvicorn app:main --lifespan off\n```\n\n### Logging\n\n```bash\n# Log level\nuvicorn app:main --log-level info\n\n# Available levels: trace, debug, info, warning, error, critical\n\n# Enable or disable access log\nuvicorn app:main --access-log\nuvicorn app:main --no-access-log\n```\n\nCustom log config (via programmatic API):\n\n```python\nimport logging.config\n\nLOG_CONFIG = {\n    \"version\": 1,\n    \"disable_existing_loggers\": False,\n    \"formatters\": {\n        \"default\": {\"format\": \"%(asctime)s %(levelname)s %(name)s %(message)s\"},\n    },\n    \"handlers\": {\n        \"default\": {\"class\": \"logging.StreamHandler\", \"formatter\": \"default\"},\n    },\n    \"root\": {\"handlers\": [\"default\"], \"level\": \"INFO\"},\n}\n```\n\nPass via `uvicorn.Config(log_config=LOG_CONFIG, ...)`.\n\n### Reload (Development Only)\n\n```bash\n# Watch all files for changes\nuvicorn app:main --reload\n\n# Watch specific directories\nuvicorn app:main --reload --reload-dir src/\n\n# Include/exclude specific patterns\nuvicorn app:main --reload --reload-include \"*.html\" --reload-exclude \"*.log\"\n```\n\n### Programmatic API\n\n```python\nimport uvicorn\n\n# Simple: run() is a blocking call, wraps Config + Server\nuvicorn.run(\"app:main\", host=\"0.0.0.0\", port=8000, workers=4)\n\n# Advanced: Config + Server for custom lifecycle control\nimport asyncio\nfrom uvicorn import Config, Server\n\nconfig = Config(\n    app=\"app:main\",\n    host=\"0.0.0.0\",\n    port=8000,\n    loop=\"uvloop\",\n    http=\"httptools\",\n    log_level=\"info\",\n    access_log=True,\n)\nserver = Server(config)\n\nasyncio.run(server.serve())\n```\n\n### Uvicorn vs Granian Comparison\n\n| Feature | Uvicorn | Granian |\n|---------|---------|---------|\n| Core language | Python | Rust (hyper + tokio) |\n| RSGI support | No | Yes (native) |\n| HTTP/2 native | No (via h2 package) | Yes |\n| Threading model | GIL-bound workers | `workers` or `runtime` |\n| Performance | Moderate | Higher throughput |\n| Memory footprint | Higher | Lower |\n| Production default | Acceptable | Preferred |\n\n<workflow>\n\n## Workflow\n\n### Step 1: Install Uvicorn\n\n```bash\n# Minimal install\npip install uvicorn\n\n# With performance extras (uvloop + httptools)\npip install \"uvicorn[standard]\"\n```\n\n### Step 2: Choose Worker Strategy\n\nFor development, use a single worker with `--reload`. For production, choose one of:\n\n- `uvicorn app:main --workers N` — simplest multi-process option\n- `gunicorn -k uvicorn.workers.UvicornWorker --workers N` — production-grade process manager with signal handling and graceful restarts\n\n### Step 3: Select Event Loop and HTTP Parser\n\nFor production performance, always use uvloop and httptools (included in `uvicorn[standard]`):\n\n```bash\nuvicorn app:main --loop uvloop --http httptools\n```\n\n### Step 4: Configure Lifespan and Logging\n\nSet `--lifespan on` if the app has startup/shutdown handlers. Configure log level and access logging to match the deployment environment.\n\n### Step 5: Add SSL or Place Behind Reverse Proxy\n\nFor publicly exposed services, either terminate SSL at uvicorn with `--ssl-keyfile` / `--ssl-certfile`, or proxy through nginx/Caddy and connect uvicorn over a Unix socket or localhost port.\n\n</workflow>\n\n<guardrails>\n\n## Guardrails\n\n- **Never use `--reload` in production** -- reload watches the filesystem and has performance overhead and security risk. It is strictly a development tool.\n- **Use gunicorn + uvicorn workers for multi-process production** -- `gunicorn -k uvicorn.workers.UvicornWorker` provides proper signal handling, graceful restarts, and process supervision that `--workers` alone does not.\n- **Set `--workers` to `2 * CPU_CORES + 1` as a starting point** -- tune based on measured CPU and memory utilization under load.\n- **Use uvloop and httptools for production performance** -- install `uvicorn[standard]` and set `--loop uvloop --http httptools` explicitly.\n- **Always set explicit `--host` in containers** -- the default `127.0.0.1` will not accept connections from outside the container. Use `--host 0.0.0.0` or bind to a specific interface.\n- **For Litestar apps, prefer Granian** -- Granian provides native Litestar CLI integration via `GranianPlugin` and higher throughput. See `flow:granian`.\n- **Do not use `uvicorn.run()` with `workers > 1` inside an `if __name__ == \"__main__\"` guard on Windows** -- multiprocessing on Windows requires the spawn start method and `__main__` guard, but worker spawning behavior differs from POSIX. Prefer gunicorn on Linux/macOS for multi-worker production.\n\n</guardrails>\n\n<validation>\n\n### Validation Checkpoint\n\nBefore delivering a Uvicorn deployment configuration, verify:\n\n- [ ] `--reload` is absent from any production configuration\n- [ ] Multi-process production uses gunicorn + `UvicornWorker` or `--workers` with documented reasoning\n- [ ] `--workers` count is justified (CPU core formula or measured target)\n- [ ] `--loop uvloop` and `--http httptools` are set for production\n- [ ] `--host` is explicitly set (not relying on `127.0.0.1` default in containers)\n- [ ] SSL flags are present for publicly exposed services (or reverse proxy is documented)\n- [ ] Granian was evaluated as an alternative and preference documented\n\n</validation>\n\n<example>\n\n## Example\n\n**Task:** Production deployment of a Starlette ASGI app on an 8-core host with SSL, structured logging, and graceful restarts.\n\nUsing gunicorn + uvicorn worker class (recommended):\n\n```bash\ngunicorn app:main \\\n  -k uvicorn.workers.UvicornWorker \\\n  --workers 17 \\\n  --bind 0.0.0.0:8443 \\\n  --keyfile /etc/ssl/private/app.key \\\n  --certfile /etc/ssl/certs/app.crt \\\n  --log-level info \\\n  --access-logfile -\n```\n\nUsing programmatic Config/Server for custom lifecycle control:\n\n```python\nimport asyncio\nimport signal\nfrom uvicorn import Config, Server\n\nconfig = Config(\n    app=\"app:main\",\n    host=\"0.0.0.0\",\n    port=8000,\n    workers=1,  # Config+Server handles a single process; use gunicorn for multi-worker\n    loop=\"uvloop\",\n    http=\"httptools\",\n    lifespan=\"on\",\n    log_level=\"info\",\n    access_log=True,\n    ssl_keyfile=\"/etc/ssl/private/app.key\",\n    ssl_certfile=\"/etc/ssl/certs/app.crt\",\n)\nserver = Server(config)\n\nloop = asyncio.new_event_loop()\nloop.run_until_complete(server.serve())\n```\n\nFor Litestar apps, prefer Granian with zero-config integration:\n\n```python\nfrom litestar import Litestar\nfrom litestar.plugins.granian import GranianPlugin\n\napp = Litestar(\n    route_handlers=[...],\n    plugins=[GranianPlugin()],\n)\n```\n\n```bash\nlitestar --app app:app run --host 0.0.0.0 --port 8000\n```\n\n</example>\n\n---\n\n## Official References\n\n- <https://www.uvicorn.org/>\n- <https://www.uvicorn.org/deployment/>\n- <https://github.com/encode/uvicorn>\n- <https://pypi.org/project/uvicorn/>\n\n## Shared Styleguide Baseline\n\n- Use shared styleguides for generic language/framework rules to reduce duplication in this skill.\n- [General Principles](https://github.com/cofin/flow/blob/main/templates/styleguides/general.md)\n- [Python](https://github.com/cofin/flow/blob/main/templates/styleguides/languages/python.md)\n- Keep this skill focused on tool-specific workflows, edge cases, and integration details.","tags":["uvicorn","flow","cofin","agent-skills","ai-agents","beads","claude-code","codex","cursor","developer-tools","gemini-cli","opencode"],"capabilities":["skill","source-cofin","skill-uvicorn","topic-agent-skills","topic-ai-agents","topic-beads","topic-claude-code","topic-codex","topic-cursor","topic-developer-tools","topic-gemini-cli","topic-opencode","topic-plugin","topic-slash-commands","topic-spec-driven-development"],"categories":["flow"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/cofin/flow/uvicorn","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add cofin/flow","source_repo":"https://github.com/cofin/flow","install_from":"skills.sh"}},"qualityScore":"0.455","qualityRationale":"deterministic score 0.46 from registry signals: · indexed on github topic:agent-skills · 11 github stars · SKILL.md body (8,968 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-04-24T07:03:20.896Z","embedding":null,"createdAt":"2026-04-23T13:04:02.578Z","updatedAt":"2026-04-24T07:03:20.896Z","lastSeenAt":"2026-04-24T07:03:20.896Z","tsv":"'/cofin/flow/blob/main/templates/styleguides/general.md)':1119 '/cofin/flow/blob/main/templates/styleguides/languages/python.md)':1123 '/deployment/':1092 '/encode/uvicorn':1095 '/etc/ssl/certs/app.crt':250,975,1040 '/etc/ssl/certs/ca-bundle.crt':255 '/etc/ssl/private/app.key':246,973,1037 '/project/uvicorn/':1098 '0.0.0.0':108,118,132,172,240,434,459,786,970,1006,1084 '1':180,343,525,735,818,1010 '127.0.0.1':775,908 '17':968 '2':178,544,732 '3':588 '4':122,152,170,438,616 '5':642 '8':945 '8000':110,120,134,173,436,461,1008,1086 '8443':242,971 'absent':865 'accept':521,778 'access':316,322,329,469,634,981,1032 'access-log':321 'access-logfil':980 'activ':4 'add':643 'advanc':439 'alon':726 'altern':83,930 'alway':275,598,767 'api':26,336,417 'app':61,105,115,129,149,165,192,202,218,229,237,262,270,280,290,299,319,325,387,394,405,431,455,456,562,609,626,795,942,963,1002,1003,1054,1071,1079,1080,1081 'asctim':351 'asgi':11,15,46,60,100,941 'asyncio':196,205,447,992 'asyncio.new':1045 'asyncio.run':475 'auto':3,258,273 'auto-activ':2 'avail':305 'base':82,213,741 'baselin':1101 'bash':98,138,183,208,235,257,295,380,528,607,961,1077 'basic':99 'behavior':841 'behind':647 'bind':171,788,969 'block':425 'bound':506 'built':48 'c':212 'c-base':211 'ca':253 'call':426 'case':1134 'cert':254 'certfil':249,665,974,1039 'chang':385 'checkpoint':855 'choos':545,558 'class':160,361,959 'cli':9,29,96,802 'command':10 'communiti':56 'comparison':480 'complet':1050 'config':333,341,374,376,428,440,451,453,454,474,998,1000,1001,1011,1043,1060 'config/server':31,985 'configur':13,18,35,234,617,630,861,869 'connect':671,779 'consid':74 'contain':772,783,911 'control':445,989 'core':484,734,887,946 'count':883 'cpu':733,744,886 'critic':312 'custom':331,443,987 'debug':308 'default':197,223,259,349,360,364,367,520,774,909 'deliv':857 'deploy':34,70,639,860,937 'detail':1137 'develop':67,123,378,549,701 'differ':842 'dir':399 'directori':392 'disabl':315,344 'document':880,924,933 'duplic':1111 'edg':1133 'either':654 'enabl':260,313 'entir':288 'environ':640 'error':311 'evalu':927 'event':19,181,278,287,590,1046 'exampl':934 'exclud':414 'exist':345 'explicit':766,769,903 'expos':652,918 'extra':536 'fallback':200,227 'fals':347 'fast':45 'fastapi':103 'faster':210 'featur':481 'file':383 'filesystem':689 'flag':913 'flow':77,810 'focus':1127 'footprint':516 'format':350 'formatt':348,363 'formula':176,888 'gain':190 'general':1115 'generic':1106 'gil':505 'gil-bound':504 'github.com':1094,1118,1122 'github.com/cofin/flow/blob/main/templates/styleguides/general.md)':1117 'github.com/cofin/flow/blob/main/templates/styleguides/languages/python.md)':1121 'github.com/encode/uvicorn':1093 'grace':585,719,953 'grade':578 'granian':75,78,479,483,797,798,811,925,1056 'granianplugin':805,1070,1076 'guard':824,837 'guardrail':680 'gunicorn':157,164,571,704,712,846,875,956,962,1018 'h11':222,232 'h2':499 'handl':583,718,1013 'handler':265,359,366,629,1074 'higher':85,513,517,807 'host':107,117,131,239,433,458,770,785,901,947,1005,1083 'html':411 'http':206,220,231,464,593,613,764,895,1025 'http/2':92,495 'httptool':52,209,221,465,538,602,614,753,765,896,1026 'hyper':488 'implement':207 'import':7,338,419,446,450,991,993,997,1065,1069 'includ':410,603 'include/exclude':401 'info':304,309,369,468,979,1031 'insid':819 'instal':526,530,532,540,757 'integr':803,1061,1136 'interfac':792 'intern':147 'invoc':30 'justifi':885 'k':167,572,713,965 'keep':1124 'keyfil':245,662,972,1036 'languag':485 'language/framework':1107 'level':297,303,306,368,467,632,978,1030 'levelnam':353 'lifecycl':444,988 'lifespan':23,256,264,272,282,286,292,618,622,1027 'lightn':44 'lightning-fast':43 'linux/macos':848 'litestar':101,794,801,1053,1064,1066,1072,1078 'litestar.plugins.granian':1068 'load':749 'localhost':678 'log':24,294,296,302,317,323,330,332,340,373,375,415,466,470,620,631,635,951,977,1029,1033 'log-level':301,976 'logfil':982 'logger':346 'logging.config':339 'logging.streamhandler':362 'loop':20,182,194,204,462,591,611,762,892,1023,1044,1047 'loop.run':1048 'lower':87,518 'main':106,116,130,150,166,193,203,219,230,238,271,281,291,300,320,326,388,395,406,432,457,563,610,823,836,964,1004 'manag':580 'match':637 'measur':743,890 'memori':88,515,746 'messag':357 'method':834 'minim':529 'model':137,503 'moder':512 'multi':140,154,568,709,851,871,1021 'multi-process':139,153,567,708,870 'multi-work':850,1020 'multipl':112 'multiprocess':146,827 'n':565,575 'name':355,822 'nativ':91,494,496,800 'never':681 'nginx/caddy':669 'no-access-log':327 'nproc':179 'offici':1087 'one':559 'option':570 'outsid':781 'overhead':693 'packag':500 'parser':594 'pass':370 'pattern':403 'perform':511,535,597,692,756 'pip':531,539 'place':646 'plugin':1075 'point':175,739 'port':109,119,133,241,435,460,679,1007,1085 'posix':844 'prefer':522,796,845,932,1055 'present':915 'principl':1116 'process':141,155,569,579,710,722,872,1016 'produc':27 'product':69,72,111,163,187,216,519,557,577,596,685,711,755,853,868,873,900,936 'production-grad':576 'programmat':25,335,416,984 'proper':716 'provid':715,799 'proxi':649,667,922 'public':651,917 'pure':198,224 'pypi.org':1097 'pypi.org/project/uvicorn/':1096 'python':59,199,225,337,418,486,990,1062,1120 'quick':94 'reason':881 'recommend':161,185,214,960 'reduc':1110 'refer':95,1088 'reli':906 'reload':127,135,377,389,396,398,407,409,413,555,683,686,863 'reload-dir':397 'reload-exclud':412 'reload-includ':408 'requir':830 'restart':586,720,954 'revers':648,921 'risk':696 'root':365 'rout':1073 'rsgi':490 'rule':1108 'run':276,422,1082 'runtim':510 'rust':81,487 'rust-bas':80 'safer':226 'secur':695 'see':76,809 'select':21,589 'server':12,16,38,47,429,441,452,472,473,999,1012,1041,1042 'server.serve':476,1051 'servic':653,919 'set':621,729,761,768,898,904 'share':1099,1103 'signal':582,717,994 'signific':188 'simpl':421 'simplest':566 'singl':124,552,1015 'skill':39,1114,1126 'skill-uvicorn' 'skip':266,285 'socket':676 'source-cofin' 'spawn':832,840 'specif':391,402,791,1131 'src':400 'ssl':22,233,244,248,252,644,656,661,664,912,949,1035,1038 'ssl-ca-cert':251 'ssl-certfil':247,663 'ssl-keyfil':243,660 'standard':57,542,606,759 'starlett':102,940 'start':174,738,833 'startup/shutdown':277,628 'step':524,543,587,615,641 'strategi':547 'strict':699 'structur':950 'styleguid':1100,1104 'supervis':723 'support':93,491 'target':891 'task':935 'termin':655 'thread':502 'throughput':86,189,514,808 'tokio':489 'tool':702,1130 'tool-specif':1129 'topic-agent-skills' 'topic-ai-agents' 'topic-beads' 'topic-claude-code' 'topic-codex' 'topic-cursor' 'topic-developer-tools' 'topic-gemini-cli' 'topic-opencode' 'topic-plugin' 'topic-slash-commands' 'topic-spec-driven-development' 'trace':307 'true':471,1034 'tune':740 'unix':675 'usag':32,97 'use':36,65,89,145,550,599,682,703,750,784,814,874,955,983,1017,1102 'util':747 'uvicorn':1,6,8,14,28,37,40,104,114,128,143,148,158,191,201,217,228,236,269,279,289,298,318,324,386,393,404,420,449,477,482,527,533,541,561,605,608,658,672,705,758,859,957,996 'uvicorn.config':372 'uvicorn.run':430,815 'uvicorn.workers.uvicornworker':168,573,714,966 'uvicornwork':876 'uvloop':50,184,195,463,537,600,612,751,763,893,1024 'valid':854 'verifi':862 'version':342 'via':142,156,334,371,498,804 'vs':478 'warn':310 'watch':381,390,687 'wide':64 'window':826,829 'worker':17,113,121,125,136,144,151,159,169,177,437,507,508,546,553,564,574,706,725,730,817,839,852,878,882,958,967,1009,1022 'workflow':523,1132 'workload':73 'wrap':427 'www.uvicorn.org':1089,1091 'www.uvicorn.org/deployment/':1090 'yes':493,501 'zero':1059 'zero-config':1058","prices":[{"id":"00676656-9663-4765-9b63-447c213a9ed6","listingId":"bd608c4e-9048-4aad-b81f-94f0387bde5c","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"cofin","category":"flow","install_from":"skills.sh"},"createdAt":"2026-04-23T13:04:02.578Z"}],"sources":[{"listingId":"bd608c4e-9048-4aad-b81f-94f0387bde5c","source":"github","sourceId":"cofin/flow/uvicorn","sourceUrl":"https://github.com/cofin/flow/tree/main/skills/uvicorn","isPrimary":false,"firstSeenAt":"2026-04-23T13:04:02.578Z","lastSeenAt":"2026-04-24T07:03:20.896Z"}],"details":{"listingId":"bd608c4e-9048-4aad-b81f-94f0387bde5c","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"cofin","slug":"uvicorn","github":{"repo":"cofin/flow","stars":11,"topics":["agent-skills","ai-agents","beads","claude-code","codex","context-driven-development","cursor","developer-tools","gemini-cli","opencode","plugin","slash-commands","spec-driven-development","subagents","tdd","workflow"],"license":"apache-2.0","html_url":"https://github.com/cofin/flow","pushed_at":"2026-04-19T23:22:27Z","description":"Context-Driven Development toolkit for AI agents — spec-first planning, TDD workflow, and Beads integration.","skill_md_sha":"82c7f7fb7ff9b9cfa6fab6958ff12e0ed488d6f9","skill_md_path":"skills/uvicorn/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/cofin/flow/tree/main/skills/uvicorn"},"layout":"multi","source":"github","category":"flow","frontmatter":{"name":"uvicorn","description":"Auto-activate for uvicorn imports, uvicorn CLI commands, ASGI server configuration. Uvicorn ASGI server: worker configuration, event loop selection, SSL, lifespan, logging, programmatic API. Produces uvicorn CLI invocations, Config/Server usage, and deployment configurations. Use when: deploying ASGI apps with uvicorn, configuring workers/reload, setting up SSL, or running development servers. Note: Granian is preferred over uvicorn for production workloads — see flow:granian."},"skills_sh_url":"https://skills.sh/cofin/flow/uvicorn"},"updatedAt":"2026-04-24T07:03:20.896Z"}}