Modal
1.5.5 (2026-08-28) commercialModal is a cloud platform for running, scaling, and deploying Python code and machine learning models serverlessly.
sb = modal.Sandbox.create(
"sleep", "infinity",
outbound_domain_allowlist=["*"],
outbound_cidr_allowlist=["0.0.0.0/0"],
app=app,
)
# ... dependencies installed ...
sb._experimental_set_outbound_network_policy(
outbound_domain_allowlist=["api.openai.com", "*.github.com"],
outbound_cidr_allowlist=[],
)
sb = modal.Sandbox.create(
"bash", "-c", "python3 -m http.server 8080",
app=my_app,
)
creds = sb.create_connect_token(user_metadata={"user_id": "alice"}, port=8080)
import requests
resp = requests.get(creds.url, headers={"Authorization": f"Bearer {creds.token}"})
print(resp.text)
sb = modal.Sandbox.create(
"sleep", "infinity",
outbound_cidr_allowlist=["52.0.0.0/8", "10.0.1.0/24"],
app=app,
)
sb = modal.Sandbox.create(
"python3", "-m", "http.server", "8080",
readiness_probe=modal.Probe.with_tcp(8080),
app=sb_app,
)
sb.wait_until_ready()
# server is now accepting connections
sb.terminate()
sb.detach()
sb = modal.Sandbox.create(
"bash", "-c", "sleep 5 && touch /tmp/ready && sleep 3600",
readiness_probe=modal.Probe.with_exec(
"sh", "-c", "test -f /tmp/ready",
interval_ms=250,
),
app=sb_app,
)
sb.wait_until_ready()
p = sb.exec("cat", "/tmp/ready")
sb.terminate()
sb.detach()
sb = modal.Sandbox.create(
app=sb_app,
timeout=24*60*60,
idle_timeout=30*60,
)
sb.detach()
modal --profile <profile-name> run my_app.py
modal --profile my-staging-profile run my_app.py
import modal
app = modal.App.from_name('my-app')
async for entry in app.logs.stream():
print(entry)
HTTPS_PROXY=http://proxy.corp.example.com:8080 modal deploy my_app.py
MODAL_SANDBOX_V2=1 modal run my_sandbox_app.py
modal image logs my-app-name
modal billing rates Summary
Modal is a cloud platform for running, scaling, and deploying Python code and machine learning models serverlessly.
Release history
- docs update
Modal Sandboxes gain granular outbound/inbound network controls, runtime policy updates, and HTTP/WebSocket Connect Tokens.
└──▷ USE ITLock down an agentic Sandbox mid-session: start with broad access for dependency installation, then narrow to only the domains the tool actually needs.sb = modal.Sandbox.create( "sleep", "infinity", outbound_domain_allowlist=["*"], outbound_cidr_allowlist=["0.0.0.0/0"], app=app, ) # ... dependencies installed ... sb._experimental_set_outbound_network_policy( outbound_domain_allowlist=["api.openai.com", "*.github.com"], outbound_cidr_allowlist=[], )Serve HTTP from inside a Sandbox with per-request authenticated access, forwarding verified caller metadata to the application.sb = modal.Sandbox.create( "bash", "-c", "python3 -m http.server 8080", app=my_app, ) creds = sb.create_connect_token(user_metadata={"user_id": "alice"}, port=8080) import requests resp = requests.get(creds.url, headers={"Authorization": f"Bearer {creds.token}"}) print(resp.text)Restrict a Sandbox to only two IP ranges while keeping all other outbound traffic blocked, for tightly scoped egress control.sb = modal.Sandbox.create( "sleep", "infinity", outbound_cidr_allowlist=["52.0.0.0/8", "10.0.1.0/24"], app=app, )- ›Adds
block_network=Trueparameter to modal.Sandbox.create() to drop all outbound traffic from a Sandbox. - ›Adds
outbound_cidr_allowlistparameter to modal.Sandbox.create() to restrict outbound traffic to specified CIDR ranges (any protocol). - ›Adds
outbound_domain_allowlistparameter (Beta) to modal.Sandbox.create() to restrict outbound TLS traffic (port 443 only) to specified domain names, with wildcard*.prefix support for subdomains; blocked connections are logged to the Sandbox system output stream. - ›Adds
inbound_cidr_allowlistparameter to modal.Sandbox.create() to restrict which source IPs can connect inbound to the Sandbox through tunnels and Connect Tokens. - ›Adds _experimental_set_outbound_network_policy() method (Python) / sb.updateNetworkPolicy() (JS) / sb.UpdateNetworkPolicy() (Go) to replace the outbound network policy of a running Sandbox without restarting it; new policy takes effect immediately and terminates established connections that no longer match.
+3 moreshow less
- ›Adds sb.create_connect_token(user_metadata=..., port=...) (Python) / sb.createConnectToken() (JS) / sb.CreateConnectToken() (Go) to generate Sandbox Connect Tokens for authenticated HTTP and WebSocket access; tokens can be passed via Authorization header,
_modal_connect_tokenquery param, or_modal_connect_tokencookie; the server receives an unspoofable X-Verified-User-Data header containing the JSON-serialized metadata. - ›Adds
h2_portsparameter to modal.Sandbox.create() to expose HTTP/2 + TLS tunnels from a Sandbox, complementing the existingencrypted_ports(HTTP/1.1) andunencrypted_portsoptions. - ›Allows
outbound_cidr_allowlistandoutbound_domain_allowlistto be combined additively — traffic matching either list is permitted.
- ›Adds
- docs update
Modal Sandboxes add readiness probes, idle timeouts, and lifecycle events for secure untrusted-code execution
└──▷ USE ITWait for an HTTP server inside a Sandbox to be ready before sending traffic — avoids hand-rolling polling logic.sb = modal.Sandbox.create( "python3", "-m", "http.server", "8080", readiness_probe=modal.Probe.with_tcp(8080), app=sb_app, ) sb.wait_until_ready() # server is now accepting connections sb.terminate() sb.detach()Gate further Sandbox work on a setup script completing by probing for a sentinel file, rather than sleeping a fixed amount of time.sb = modal.Sandbox.create( "bash", "-c", "sleep 5 && touch /tmp/ready && sleep 3600", readiness_probe=modal.Probe.with_exec( "sh", "-c", "test -f /tmp/ready", interval_ms=250, ), app=sb_app, ) sb.wait_until_ready() p = sb.exec("cat", "/tmp/ready") sb.terminate() sb.detach()Run a long-lived Sandbox (up to 24 h) that self-terminates after 30 minutes of inactivity instead of billing for idle time.sb = modal.Sandbox.create( app=sb_app, timeout=24*60*60, idle_timeout=30*60, ) sb.detach()- ›Adds
readiness_probeparameter to Sandbox.create(...) supporting modal.Probe.with_tcp(port) (TCP probe) and modal.Probe.with_exec(cmd, interval_ms=...) (exec probe) so you can block until a Sandbox service is ready via sb.wait_until_ready(). - ›Adds
idle_timeoutparameter to Sandbox.create(...) to auto-terminate a Sandbox after inactivity — a Sandbox is considered active if sb.exec(...) is running, sb.stdin.write() is being called, or a Tunnel TCP connection is open. - ›Adds
timeoutparameter to Sandbox.create(...) configurable up to 24 hours (default: 5 minutes). - ›New
modal.Sandboxinterface supportsSandbox.create, sb.exec(...), sb.terminate(), sb.detach(), sb.poll(), and sb.wait_until_ready() for managing secure containers at runtime. - ›Introduces a five-stage Sandbox lifecycle — Created, Scheduled, Started, Ready (only when readiness probes are configured), and Finished — observable via the dashboard and sandbox.poll() exit codes.
+1 moreshow less
- ›TypeScript (
modalnpm package) and Go (github.com/modal-labs/modal-client/go) SDKs now expose the full Sandbox API including modal.sandboxes.create(...), sb.exec(...), Probe.withTcp(port), Probe.withExec(cmd, { intervalMs }), and sb.waitUntilReady().
- ›Adds
- docs update
Modal 1.5.5 adds Sandbox log retrieval by time range, default RBAC role config, and a global
--profileCLI flag└──▷ TRY ITSwitch to a non-default Modal profile for a one-off command without editing config.$ modal --profile <profile-name> run my_app.py
└──▷ BREAKING ON UPGRADE- !Several undocumented APIs on Modal SDK object types are deprecated in 1.5.5 and will be removed in version 1.6.0 — check for deprecation warnings before upgrading.
- 1.5.5 (2026-08-28)
Modal 1.5.5 adds Sandbox log fetching/tailing, configurable default RBAC roles for Restricted Environments, and a global
--profileCLI option.└──▷ TRY ITSelect a non-default profile on the fly without changing your config file, useful when switching between workspaces in CI.$ modal --profile my-staging-profile run my_app.py
- ›Adds
modal.Sandbox.logsAPI with fetch() for date/time-range log retrieval and tail() for the most recent logs from a Sandbox's entrypoint process. - ›Adds a
--profileglobal option to themodalCLI for ad hoc profile selection without modifying configuration. - ›Enables configuring the default role when creating a new Restricted Environment via the CLI or SDK.
- ›Adds
- snapshot-20260820
Modal 1.5.4 adds a high-performance Sandbox backend, App/Image logs APIs, billing rates API, and fractional autoscaler concurrency
└──▷ USE ITStream live logs from a deployed App to monitor it in real time from a script.import modal app = modal.App.from_name('my-app') async for entry in app.logs.stream(): print(entry)Opt into HTTP proxy support for the Modal client via environment variables when running behind a corporate proxy.$ HTTPS_PROXY=http://proxy.corp.example.com:8080 modal deploy my_app.py- ›Enables a new high-performance Sandbox backend via
MODAL_SANDBOX_V2=1environment variable, delivering substantially higher creation rates and concurrency; becomes the default in SDK version 1.6.0. - ›Adds
App.logsAPI with fetch(), tail(), and stream() methods to retrieve all logs from an App programmatically. - ›Adds
Image.logsAPI with fetch() and tail() methods to retrieve Image build logs programmatically. - ›Adds
modal image logsCLI command for accessing Image build logs from the command line. - ›Adds Workspace.billing.rates() API and
modal billing ratesCLI to query current pricing structure for a workspace.
+33 moreshow less
- ›Function.update_autoscaler() and Server.update_autoscaler() now return the complete autoscaler configuration state after applying an update.
- ›The
target_concurrencyparameter in @app.server() and Server.update_autoscaler() now accepts fractional values for finer-grained autoscaling control. - ›Adds
Function.logs,Server.logs, andFunctionCall.logsAPIs, each exposing stream(), fetch(), and tail() methods. - ›Adds modal.Workspace.billing.summary() method and
modal billing summaryCLI to see workspace-level spend broken down by category, credit usage, and compute reservation impact. - ›Adds modal.Environment.billing.summary() method and
modal environment billing summaryCLI for environment-level spend summaries. - ›Introduces
modal.Environment.rolesinterface andmodal environment rolesCLI for managing RBAC permissions, replacing the deprecatedmodal.Environment.membersinterface andmodal environment membersCLI. - ›Adds
--compute-regionoption (repeatable) tomodal endpoint createto configure the region where Endpoint containers run. - ›Adds modal.Workspace.settings.list() method and
modal workspace settings listCLI to view current workspace-level settings. - ›Adds modal.Workspace.settings.set() method and
modal workspace settings setCLI to programmatically configure workspace settings. - ›Adds
modal.typesmodule exposing dataclasses returned from public SDK methods as public API, useful for type annotations. - ›modal.Function.with_options() now accepts a
routing_regionargument to configure regional routing dynamically at invocation time. - ›Adds
--gracefulflag tomodal container stopCLI, allowing a container to finish in-flight inputs before exiting rather than having them cancelled. - ›
modal container logsCLI now includes logs from the container startup phase. - ›modal.Sandbox.reload_volumes() now accepts a
timeoutargument (default 55 seconds) and raisesmodal.exception.TimeoutErrorif the reload does not complete in time. - ›Introduces @app.server() decorator and
modal.Serverobject as a new serverless compute primitive optimized for low-latency HTTP applications. - ›Introduces
modal endpointCLI for deploying production-ready LLM inference endpoints with minimal configuration. - ›Adds workspace.billing.report() and environment.billing.report() methods with resource-level cost breakdown by CPU, memory, and GPU type.
- ›Adds
modal environment billingCLI for generating environment-scoped billing reports. - ›Adds workspace.proxy_tokens.create(), workspace.proxy_tokens.list(), and related methods on
modal.Workspace, plus amodal workspace proxy-tokensCLI for managing proxy tokens. - ›Adds
modal workspace membersCLI for querying workspace membership information. - ›Adds
modal curlexperimental CLI command for making authenticated requests to endpoints without manually passing proxy token headers. - ›
modal app rollbacknow accepts a--strategyoption (rollingorrecreate), matchingmodal deployandmodal app rollover. - ›modal.Sandbox.create_connect_token() now accepts a
port=argument to scope connect tokens to a custom port. - ›The Modal Python client now supports HTTP CONNECT and SOCKS4/5 proxies via standard
HTTPS_PROXYandALL_PROXYenvironment variables; install extras withuv pip install 'modal[api-proxy-support]', or opt out by settingMODAL_DISABLE_API_PROXY=1ordisable_api_proxy = truein.modal.toml. - ›Introduces named Images via modal.Image.publish() (optionally with
'{name}:{tag}'format) and modal.Image.from_name() for Modal-native image registry functionality. - ›Adds
modal image namesCLI to view current name assignments for published Images. - ›Adds
version=parameter to modal.Function.from_name() and modal.Cls.from_name() to pin invocations to a specific deployed version of a Function. - ›Adds
outbound_domain_allowlist=[...]parameter to modal.Sandbox.create() to restrict which domains Sandbox processes can connect to, with denials recorded in App logs. - ›Adds
modal skillsCLI withmodal skills installandmodal skills updatesubcommands for managing a foundational Modal agent skill. - ›Introduces
modal.Workspaceobject with workspace.members.list() method for programmatic workspace configuration management. - ›Adds sandbox.filesystem.watch() method to the Sandbox Filesystem API for improved latency and reliability over the deprecated modal.Sandbox.watch().
- ›modal.Sandbox.snapshot_filesystem() and modal.Sandbox.snapshot_directory() now accept a
ttl=keyword argument (default30 * 24 * 3600seconds) to configure snapshot image retention. - ›modal.Sandbox.snapshot_directory() now accepts a
timeout=keyword argument (default 55 seconds), raisingmodal.exception.TimeoutErrorif the snapshot does not complete in time.
└──▷ BREAKING ON UPGRADE- !The new Sandbox backend (
MODAL_SANDBOX_V2=1) does not support the deprecated FileIO-based Sandbox filesystem API; code currently issuing FileIO deprecation warnings must be migrated before enabling the flag. - !modal.Sandbox.snapshot_filesystem() and modal.Sandbox.snapshot_directory() now default to
ttl=30 * 24 * 3600(30 days), replacing the previous behavior of persisting snapshot Images indefinitely; passttl=Noneto retain the old behavior. - !modal.Sandbox.snapshot_directory() now defaults to a 55-second
timeout=and raisesmodal.exception.TimeoutErrorif exceeded, replacing the previous behavior of waiting indefinitely. - !Several deprecated static methods (.delete() and .create_deployed()) on Modal storage objects (
modal.Volume, etc.) have been removed; use .objects.delete() and .objects.create() instead. - !The existing
modal.billing.workspace_billing_reportfunction is replaced by the new workspace.billing.report() API.
- ›Enables a new high-performance Sandbox backend via
- 1.5.4 (2026-08-12)└──▷ TRY ITOpt into the faster Sandbox backend to handle higher concurrency workloads without any code changes.
$ MODAL_SANDBOX_V2=1 modal run my_sandbox_app.pyStream live logs from a deployed App to monitor execution in real time.$ modal image logs my-app-nameCheck current workspace pricing rates before scaling up GPU workloads.$ modal billing rates- ›Adds Workspace.billing.rates() API to query current workspace pricing structure programmatically.
- ›Adds
modal billing ratesCLI command to query workspace pricing from the terminal.