modal-servers
Skill4 starsChanged 3 months agoApache-2.0View on GitHub
Low-latency Modal Servers via @app.server() and modal.Server. Use when serving long-lived HTTP/WebSocket/gRPC processes with regional routing, proxy-token auth, sticky sessions, or migrating from @modal.web_server. Prefer this over Function web endpoints when request latency and concurrent in-process serving matter. Triggers on: "@app.server", "modal.Server", "Modal Server", "modal.direct", "target_concurrency", "Modal-Session-ID", "proxy token", "low-latency HTTP Modal".
We split this skill into the rules it gives an agent
8 rules. About 0 are common, 3 are distinctive, and 5 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈3
Distinctive · estimate
This author's own choices. Worth a look.
5
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 14
Use this skill when deploying a process that listens on a port inside Modal with the Server primitive (SDK 1.5.1+), optimized for …
- Very specific: line 98
Prefer unset target_concurrency over max_containers=1 for singletons (allows rolling replacement).
- Distinctive: line 105
When no containers are warm, requests are rejected with 503 (they do not queue like Function inputs).
- Very specific: line 141
Do not use @modal.method() or Function web decorators on a Server class.
- Very specific: line 147
Check startup_timeout and that the process binds the right port
- Very specific: line 155
Ensure app isn’t doing cold model load on every request — use @modal.enter + snapshots if appropriate
- Very specific: line 171
Always bind 0.0.0.0, not 127.0.0.1
- Distinctive: line 172
Do not assume request queueing or built-in retries
≈ “Common” is an estimate: at least 1 in 5 of the 308,232 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Modal Servers
Use this skill when deploying a process that listens on a port inside Modal with the Server primitive (SDK 1.5.1+), optimized for ultra-low-latency HTTP between clients and containers.
For Function-based web endpoints (fastapi_endpoint / asgi_app / wsgi_app / web_server), see modal-web-serving. For one-command LLM inference products, see modal-endpoints.
When to Use This Skill
- Serving vLLM, SGLang, or any HTTP server with minimal proxy latency
- Need regional request routing (
routing_region) close to clients - Want sticky sessions via
Modal-Session-ID - Migrating from
@modal.web_serverto@app.server - Need default authenticated ingress (proxy tokens) or explicit
unauthenticated=True - Building custom inference behind the same infrastructure as Auto Endpoints
Quick Start
import modal
import subprocess
app = modal.App("my-server")
@app.server(port=8000, unauthenticated=True)
class FileServer:
@modal.enter()
def start(self):
# Must bind 0.0.0.0 and listen on the configured port
self.proc = subprocess.Popen(
["python", "-m", "http.server", "8000", "--bind", "0.0.0.0"]
)
@modal.exit()
def stop(self):
self.proc.terminate()Deploy: modal deploy server_app.py
URL shape: https://<workspace>--<app>-<server>.<routing_region>.modal.direct/...
Retrieve programmatically: modal.Server.get_url() (see reference).
Servers vs Functions vs Web Decorators
| Concern | @app.server | @modal.web_server / web Function | .remote() Function |
| Request model | Stateless reverse proxy → port | Function inputs / ASGI bridge | Queued inputs |
| Cold zero→one | First requests may 503 until ready | Inputs queue while cold-starting | Inputs queue |
| Concurrency default | Process handles many requests; set target_concurrency to autoscale | One input unless @modal.concurrent | One input unless concurrent |
| Auth default | Requires Modal-Key / Modal-Secret unless unauthenticated=True | Often public URL patterns | N/A |
.remote() / map | No | Limited / N/A for web-only | Yes |
| Retries / input timeouts | App/client responsibility | Modal input system | Modal input system |
| Best for | Low-latency long-lived servers | Simple ASGI/WSGI/FastAPI Functions | Batch/RPC compute |
Core Configuration
@app.server(
image=image,
gpu="H100",
port=8000,
startup_timeout=30 * 60,
target_concurrency=32, # soft target for autoscaling
min_containers=0,
max_containers=10,
buffer_containers=1,
scaledown_window=10 * 60,
exit_grace_period=30, # finish in-flight before SIGTERM
routing_region="us-east", # us-east | us-west | ca-central | eu-west | ap-south
compute_region="us", # optional: pin container placement (cost multiplier)
unauthenticated=False, # default: proxy-token auth required
h2_enabled=False,
secrets=[...],
volumes={...},
enable_memory_snapshot=False,
)
class InferenceServer:
@modal.enter()
def start(self):
...Autoscaling notes
- Omit
target_concurrency→ no concurrency-based scale-out (still distributes ifmin_containers> 1). - Prefer unset
target_concurrencyovermax_containers=1for singletons (allows rolling replacement). - Dynamic tuning:
modal.Server.update_autoscaler(...)(reset on next deploy). - Containers are not ready until the port is listening; failed readiness within
startup_timeout→ failed container. - Health checks verify the port stays up; repeated failures replace the container.
Zero-to-one
When no containers are warm, requests are rejected with 503 (they do not queue like Function inputs). Clients must retry. The first request still triggers a cold start.
Authentication
Default: require headers:
Modal-Key: wk-...
Modal-Secret: ws-...Create tokens:
modal workspace proxy-tokens create
# With RBAC, scope to the Server's environment:
modal workspace proxy-tokens allow wk-... mainTesting helper (adds auth for you; higher latency): modal curl <url>/path
Public traffic: set unauthenticated=True.
RBAC: tokens must be scoped to the Environment or requests get 403.
Sticky Sessions
Send header Modal-Session-ID: <any-string> so related requests hit the same container (useful for WebSockets / conversational state).
Lifecycle
@modal.enter()starts the process binding0.0.0.0:<port>- Modal waits until the port accepts connections
- Traffic flows through the regional routing plane
- Scale-down: stop new requests →
exit_grace_periodfor in-flight → SIGTERM →@modal.exit()→ hard kill after grace
Do not use @modal.method() or Function web decorators on a Server class. Request handling is entirely the child process’s job.
Symptom Triage
503 on first traffic
- Expected at zero containers; keep
min_containers>=1or retry with backoff - Check
startup_timeoutand that the process binds the right port
401 / 403
- Missing proxy token headers, or token not allowed for this Environment
- Accidentally left
unauthenticated=Falsefor public clients
High latency still
- Move
routing_region(and optionallycompute_region/ colocate) nearer clients - Ensure app isn’t doing cold model load on every request — use
@modal.enter+ snapshots if appropriate
Migrating from @modal.web_server
- Move startup into
@modal.enteron an@app.serverclass - Revisit auth defaults and 503 cold-start behavior
- Drop Function input concurrency decorators; use
target_concurrencyinstead
Reference Map
references/server-basics.md— definition rules, URL, vs Cls/web_serverreferences/autoscaling-auth.md— concurrency, auth, sticky sessions, routingreferences/migration-from-web-server.md— migration checklist
Guardrails
- Requires Modal Python SDK 1.5.1+
- Always bind
0.0.0.0, not127.0.0.1 - Do not assume request queueing or built-in retries
- Serialization, timeouts, and retries are application concerns
- Mark regional compute pinning cost multipliers when advising users
Key References
In this repository80 other files it gives its agents.
- a11y-accessibility-designSkill
- agentic-ui-patternsSkill
- ai-native-ui-designSkill
- ai-ui-anti-patternsSkill
- ai-ui-heuristicsSkill
- calm-technology-uiSkill
- conversion-growth-designSkill
- cross-platform-designSkill
- dark-mode-designSkill
- data-visualizationSkill
- design-systemsSkill
- design-thinking-processSkill
- error-empty-statesSkill
- ethical-design-patternsSkill
- form-uxSkill
- information-architectureSkill
- interaction-design-patternsSkill
- internationalization-uiSkill
- mobile-touch-designSkill
- modal-classes-lifecycleSkill
- modal-container-imagesSkill
- modal-dicts-queuesSkill
- modal-endpointsSkill
- modal-fundamentalsSkill
- modal-gpu-computeSkill
- modal-networkingSkill
- modal-observabilitySkill
- modal-parallel-executionSkill
- modal-sandboxesSkill
- modal-scaling-performanceSkill
- modal-schedulingSkill
- modal-secretsSkill
- modal-storageSkill
- modal-web-servingSkill
- modal-workspace-adminSkill
- motion-design-principlesSkill
- notifications-permissionsSkill
- onboarding-uxSkill
- rust-api-designSkill
- rust-async-programmingSkill
- rust-cargo-masterySkill
- rust-cli-applicationsSkill
- rust-clippy-lintsSkill
- rust-closures-iteratorsSkill
- rust-compiler-internalsSkill
- rust-concurrencySkill
- rust-design-patternsSkill
- rust-editionsSkill
- rust-embeddedSkill
- rust-error-handlingSkill
- rust-game-developmentSkill
- rust-lifetimes-borrowingSkill
- rust-macrosSkill
- rust-performanceSkill
- rust-rustdocSkill
- rust-rustup-toolchainSkill
- rust-smart-pointersSkill
- rust-testing-benchmarkingSkill
- rust-type-systemSkill
- rust-unsafe-ffiSkill
- The first 60 shown.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

