modal-scaling-performance
Skill4 starsChanged 3 months agoApache-2.0View on GitHub
Autoscaling, cold start optimization, memory snapshots, concurrent inputs, dynamic batching, and high-performance LLM inference on Modal. Use when tuning scaling, reducing latency, increasing throughput, or optimizing cost.
We split this skill into the rules it gives an agent
9 rules. About 0 are common, 5 are distinctive, and 4 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈5
Distinctive · estimate
This author's own choices. Worth a look.
4
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 8
Use this skill when tuning autoscaler behavior, reducing cold start latency, configuring concurrency, enabling dynamic batching, or using …
- Distinctive: line 24
Every Function has an autoscaling container pool.
- Very specific: line 64
Use @modal.enter() for one-time setup per container
- Distinctive: line 66
Use lightweight base images
- Distinctive: line 234
Use vLLM for best throughput (continuous batching)
- Very specific: line 237
Use .spawn_map + modal run --detach for fire-and-forget batch jobs
- Distinctive: line 243
Use streaming responses to improve perceived latency
- Very specific: line 267
Use @modal.batched to accumulate inputs into efficient batches
- Very specific: line 292
Prefer modal container stop --graceful when you must drain current inputs without cancel/reschedule
≈ “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 Scaling and Performance
Use this skill when tuning autoscaler behavior, reducing cold start latency, configuring concurrency, enabling dynamic batching, or using memory snapshots for faster starts.
When to Use This Skill
- Cold starts are too slow for your use case
- Optimizing cost vs latency trade-offs
- Configuring container scaling limits
- Enabling concurrent input processing per container
- Using dynamic batching for inference workloads
- Using memory snapshots for sub-second cold starts
- High-performance LLM inference optimization
- Dynamic function configuration at runtime
- Understanding Modal's autoscaler behavior
Autoscaler Basics
Every Function has an autoscaling container pool. The autoscaler:
- Spins up containers when inputs queue
- Spins down idle containers
- Scales to zero by default when no inputs
Key Scaling Parameters
@app.function(
max_containers=100, # upper limit on containers
min_containers=1, # keep warm even when idle
buffer_containers=2, # extra containers while active
scaledown_window=300, # max idle time before shutdown (seconds, 2-1200)
)
def f():
...| Parameter | Default | Effect |
max_containers | None (unlimited) | Cap concurrent containers |
min_containers | 0 | Keep N containers warm always |
buffer_containers | 0 | Extra warm containers while active |
scaledown_window | 60 | Max seconds a container can idle |
Cold Start Optimization
Two sources of latency during cold starts:
- Queue time — waiting for a container to become ready
- Initialization time — first-invocation setup work
Reduce queue time
min_containers=1— never scale to zerobuffer_containers=2— keep spare capacityscaledown_window=300— keep containers warm longer
Reduce initialization time
- Move model downloads to build time (Volume or Image)
- Use
@modal.enter()for one-time setup per container - Minimize global scope imports
- Use lightweight base images
Concurrent Inputs
Process multiple inputs in a single container simultaneously:
@app.function()
@modal.concurrent(max_inputs=10)
def process(x):
...Useful for I/O-bound workloads where one container can handle multiple requests.
With classes
@app.cls()
class Model:
@modal.enter()
def setup(self):
self.model = load_model()
@modal.method()
@modal.concurrent(max_inputs=100, target_inputs=50)
def predict(self, x):
return self.model(x)target_inputs controls when the autoscaler starts new containers (default: 50% of max).
Dynamic Batching
Automatically batch individual requests for GPU-efficient processing:
@app.cls(gpu="A100")
class Model:
@modal.enter()
def setup(self):
self.model = load_model()
@modal.method()
@modal.batched(max_batch_size=64, wait_ms=100)
def predict(self, inputs: list[str]) -> list[str]:
return self.model.batch_predict(inputs)Individual callers send one input; Modal collects them into batches.
Memory Snapshots
Skip initialization work on most container boots — 3-10x faster cold starts:
@app.cls(enable_memory_snapshot=True)
class Model:
@modal.enter(snap=True)
def load(self):
self.model = load_model() # captured in snapshot
@modal.enter()
def post_snapshot(self):
... # runs after snapshot restore (not captured)Enable with enable_memory_snapshot=True on deployed apps (modal deploy).
GPU Memory Snapshots (Alpha)
Also capture GPU state for even faster GPU cold starts:
@app.cls(
gpu="h100",
enable_memory_snapshot=True,
experimental_options={"enable_gpu_snapshot": True},
)
class Llm:
@modal.enter(snap=True)
def init(self):
self.pipeline = pipeline(model="Qwen/Qwen3-1.7B", device_map="cuda")
# Warmup recommended — run sample inference to capture compiled state
self.pipeline([{"role": "user", "content": "warmup"}])Caveats
- Memory snapshots are worker-type-specific (6 snapshots for CPU, 2-3 for specific GPU)
- Randomness is frozen in snapshots — re-seed after restore if needed
- GPU snapshots have driver compatibility limits; review docs before using
Go SDK — Autoscaler Control
mc, _ := modal.NewClient()
fn, _ := mc.Functions.FromName(ctx, "my-app", "my_function", nil)
// Update autoscaler at runtime
minC := uint32(2)
maxC := uint32(50)
bufC := uint32(5)
fn.UpdateAutoscaler(ctx, &modal.FunctionUpdateAutoscalerParams{
MinContainers: &minC,
MaxContainers: &maxC,
BufferContainers: &bufC,
})TypeScript SDK — Autoscaler Control
import { ModalClient } from "modal";
const modal = new ModalClient();
const fn = await modal.functions.fromName("my-app", "my_function");
// Update autoscaler at runtime
await fn.updateAutoscaler({
minContainers: 2,
maxContainers: 50,
bufferContainers: 5,
scaledownWindow: 300,
});Note: Defining autoscaler config (decorators, concurrency, batching, memory snapshots) is Python-only. Go/TS SDKs can update runtime autoscaler parameters for deployed Functions.
Dynamic Function Configuration
Change compute resources, concurrency, or batching per call at runtime:
# Change GPU / resources for a specific invocation
result = f.with_options(gpu="H100").remote(data)
# Dynamic concurrency (like @modal.concurrent)
concurrent_f = f.with_concurrency(max_inputs=32)
# Dynamic batching (like @modal.batched)
batched_f = f.with_batching(max_batch_size=64, wait_ms=100)
# Compose — options merge into one pool config
concurrent_f.with_options(gpu="H100").remote(...)
# Parallel batch under a dynamic config
f.with_options(gpu="A100").spawn_map(inputs)Each distinct configuration gets its own autoscaling container pool. Avoid too many fine-grained configs. min_containers cannot be set via with_options (would multiply always-on pools).
Also available on modal.Cls: Model.with_options(...).with_concurrency(...).with_batching(...)().
For fan-out patterns using .map / .spawn / .spawn_map, see modal-parallel-execution.
Graceful Container Stop
modal container stop ta-... --gracefulWith --graceful, the container stops fetching new inputs but finishes current inputs before exiting (instead of cancelling and rescheduling them). Supported for containers running a Modal Function or Modal Server. Default stop cancels in-flight Function inputs.
High-Performance LLM Inference
Throughput optimization (batch jobs)
- Use vLLM for best throughput (continuous batching)
- FP8 quantization on Hopper+ GPUs (not FP4)
- Single-GPU-per-replica for simplicity when model fits
- Use
.spawn_map+modal run --detachfor fire-and-forget batch jobs - Store results in Volumes or external databases
Latency optimization (chatbots / HTTP)
- Minimize TTFT (time-to-first-token) and TPOT (time-per-output-token)
- Use streaming responses to improve perceived latency
- Speculative decoding for faster generation
- Smaller quantized models for memory-bound decode
min_containersto avoid cold start on first request- For ultra-low-latency HTTP serving (vLLM/SGLang/custom servers), prefer
modal-servers(@app.server) ormodal-endpointsover Function web endpoints
Cold start optimization (bursty traffic)
- Memory snapshots (
enable_memory_snapshot=True) for fast container starts - GPU memory snapshots for GPU-heavy initialization
- Model weights on Volumes (not downloaded at boot)
min_containers+buffer_containersfor warm capacity
Symptom Triage
"First request is slow, subsequent ones are fast"
- Cold start problem; use
min_containers,scaledown_window, or memory snapshots - Move model loading to
@modal.enter()or build-time
"Throughput is low for I/O-bound work"
- Enable
@modal.concurrentto handle multiple inputs per container - Increase
max_inputsfor I/O-heavy workloads
"GPU underutilized"
- Use
@modal.batchedto accumulate inputs into efficient batches - Increase
max_batch_sizefor better GPU utilization
"Cold start still slow after optimization"
- Enable memory snapshots (
enable_memory_snapshot=True) - For GPU: also enable GPU memory snapshots
- Pre-warm with sample inference in
@modal.enter(snap=True)
Reference Map
references/autoscaling.md— autoscaler behavior, parameters, dynamic updatesreferences/cold-start.md— cold start sources and optimization techniquesreferences/concurrent-inputs.md— concurrent input configurationreferences/dynamic-batching.md— batching for inference workloads
Guardrails
min_containers> 0 means you pay even when idle- Higher
scaledown_windowkeeps containers warm longer but costs more @modal.concurrentis for I/O-bound work; CPU/GPU-bound work won't benefit@modal.batchedfunction must accept and return lists- Memory snapshots only work with
modal deploy(notmodal run) - GPU memory snapshots are Alpha — validate driver/workload compatibility before production use
with_options()/with_concurrency()/with_batching()create separate container pools — don't create too many variants- Tune
target_inputsandbuffer_containersbased on traffic patterns - Prefer
modal container stop --gracefulwhen you must drain current inputs without cancel/reschedule
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-schedulingSkill
- modal-secretsSkill
- modal-serversSkill
- 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.

