Main changes
The v0.5.0 release introduces several significant architectural improvements:- Central Modal Client object: The SDKs now expose a central Modal Client object as the main entry point for interacting with Modal resources.
- Consistent interface: The interface for working with Modal object instances (Functions, Sandboxes, Images, etc.) is largely the same as before, with some naming changes.
- New serialization protocol: Calling deployed Functions and classes now uses a new protocol for payload serialization which requires the deployed apps to use the Modal Python SDK 1.2 or newer.
- No global client: Internally removed the global client (and config/profile data in global scope), moving all that to the Client type.
- Consistent parameter naming: All
Optionsstructs/interfaces renamed toParamsacross both SDKs.
Calling deployed Modal Functions and classes
This requires the referenced modal Apps to be deployed using:- Modal Python SDK 1.2 or newer
- 2025.06 image builder version or newer (see image config) OR have the
cbor2Python package installed in their image
JavaScript/TypeScript migration
Client initialization
Before (v0.4 and earlier):Complete example
Here’s a complete example showing the new API:API changes by resource
App
App
App.lookup(...)→modal.apps.fromName(...)
Cls
Cls
Cls.lookup(...)→modal.cls.fromName(...)
Function
Function
Function_.lookup(...)→modal.functions.fromName(...)
FunctionCall
FunctionCall
FunctionCall.fromId(...)→modal.functionCalls.fromId(...)
Image
Image
app.imageFromRegistry(...)→modal.images.fromRegistry(...)app.imageFromAwsEcr(...)→modal.images.fromAwsEcr(...)app.imageFromGcpArtifactRegistry(...)→modal.images.fromGcpArtifactRegistry(...)Image.fromRegistry(...)→modal.images.fromRegistry(...)Image.fromAwsEcr(...)→modal.images.fromAwsEcr(...)Image.fromGcpArtifactRegistry(...)→modal.images.fromGcpArtifactRegistry(...)Image.fromId(...)→modal.images.fromId(...)Image.delete(...)→modal.images.delete(...)
Proxy
Proxy
Proxy.fromName(...)→modal.proxies.fromName(...)
Queue
Queue
Queue.lookup(...)→modal.queues.fromName(...)Queue.fromName(...)→modal.queues.fromName(...)Queue.ephemeral(...)→modal.queues.ephemeral(...)Queue.delete(...)→modal.queues.delete(...)
Sandbox
Sandbox
app.createSandbox(image, { ... })→modal.sandboxes.create(app, image, { ... })Sandbox.fromId(...)→modal.sandboxes.fromId(...)Sandbox.fromName(...)→modal.sandboxes.fromName(...)Sandbox.list(...)→modal.sandboxes.list(...)
Secret
Secret
Secret.fromName(...)→modal.secrets.fromName(...)Secret.fromObject(...)→modal.secrets.fromObject(...)
Volume
Volume
Volume.fromName(...)→modal.volumes.fromName(...)Volume.ephemeral(...)→modal.volumes.ephemeral(...)
Parameter name changes
Type renames (Options → Params)
All parameter types have been renamed from*Options to *Params for consistency:
ClsOptions→ClsWithOptionsParamsClsConcurrencyOptions→ClsWithConcurrencyParamsClsBatchingOptions→ClsWithBatchingParamsDeleteOptions→ specific*DeleteParamstypes:QueueDeleteParamsEphemeralOptions→ specific*EphemeralParamstypes:QueueEphemeralParams,VolumeEphemeralParamsExecOptions→SandboxExecParamsLookupOptions→ specific*FromNameParamstypes:AppFromNameParams,ClsFromNameParams,FunctionFromNameParams,QueueFromNameParams- And many more…
Unit suffixes
Parameters now include explicit unit suffixes to make the API more self-documenting and prevent confusion about units.
Ms suffix):
timeout→timeoutMsidleTimeout→idleTimeoutMsscaledownWindow→scaledownWindowMsitemPollTimeout→itemPollTimeoutMspartitionTtl→partitionTtlMs
MiB suffix):
memory→memoryMiBmemoryLimit→memoryLimitMiB
Go migration
Client initialization
Before (v0.4 and earlier):Complete example
Here’s a complete example showing the new API (witherr handling omitted for brevity):
Go-specific changes
Go SDK v0.5 introduces several Go-specific improvements for better idiomaticity.
Context passing
- Many methods now require
ctx context.Contextas the first parameter - Contexts now only affect the current operation and are not used for lifecycle management of the created resources
All Params are now pointers
- All
Paramsstructs are now passed as pointers for consistency and to support optional parameters - Example:
&modal.SandboxCreateParams{...}instead ofmodal.SandboxCreateParams{...}
Field naming conventions
Field names now follow Go casing conventions:TokenId→TokenIDAppId→AppIDSandboxId→SandboxIDImageId→ImageIDFunctionId→FunctionIDUrl→URLBucketEndpointUrl→BucketEndpointURL- And similar changes for all ID and URL fields
API changes by resource
App
App
modal.AppLookup(ctx, "my-app", &modal.LookupOptions{...})→mc.Apps.FromName(ctx, "my-app", &modal.AppFromNameParams{...})
CloudBucketMount
CloudBucketMount
modal.NewCloudBucketMount(..., &modal.CloudBucketMountOptions{...})→mc.CloudBucketMounts.New(..., &modal.CloudBucketMountParams{...})
Cls
Cls
modal.ClsLookup(ctx, ..., &modal.LookupOptions{...})→mc.Cls.FromName(ctx, ..., &modal.ClsFromNameParams{...})
cls.Instance(...)→cls.Instance(ctx, ...)cls.WithOptions(modal.ClsOptions{...})→cls.WithOptions(&modal.ClsWithOptionsParams{...})cls.WithConcurrency(modal.ClsConcurrencyOptions{...})→cls.WithConcurrency(&modal.ClsWithConcurrencyParams{...})cls.WithBatching(modal.ClsBatchingOptions{...})→cls.WithBatching(&modal.ClsWithBatchingParams{...})
Function
Function
modal.FunctionLookup(ctx, ..., &modal.LookupOptions{...})→mc.Functions.FromName(ctx, ..., &modal.FunctionFromNameParams{...})
function.Remote(...)→function.Remote(ctx, ...)function.Spawn(...)→function.Spawn(ctx, ...)function.GetCurrentStats()→function.GetCurrentStats(ctx)function.UpdateAutoscaler(modal.UpdateAutoscalerOptions{...})→function.UpdateAutoscaler(ctx, &modal.FunctionUpdateAutoscalerParams{...})
FunctionCall
FunctionCall
modal.FunctionCallFromId(ctx, "call-id")→mc.FunctionCalls.FromID(ctx, "call-id")
functionCall.Get(&modal.FunctionCallGetOptions{...})→functionCall.Get(ctx, &modal.FunctionCallGetParams{...})functionCall.Cancel(&modal.FunctionCallCancelOptions{...})→functionCall.Cancel(ctx, &modal.FunctionCallCancelParams{...})
Image
Image
modal.NewImageFromRegistry(..., &modal.ImageFromRegistryOptions{...})→mc.Images.FromRegistry(ctx, ..., &modal.ImageFromRegistryParams{...})modal.NewImageFromAwsEcr(..., secret)→mc.Images.FromAwsEcr(ctx, ..., secret)modal.NewImageFromGcpArtifactRegistry(..., secret)→mc.Images.FromGcpArtifactRegistry(ctx, ..., secret)modal.NewImageFromId(ctx, ...)→mc.Images.FromID(ctx, ...)modal.ImageDelete(ctx, ..., &modal.ImageDeleteOptions{...})→mc.Images.Delete(ctx, ..., &modal.ImageDeleteParams{...})
image.DockerfileCommands(..., &modal.ImageDockerfileCommandsOptions{...})→image.DockerfileCommands(..., &modal.ImageDockerfileCommandsParams{...})image.Build(app)→image.Build(ctx, app)
Queue
Queue
modal.QueueLookup(ctx, ..., &modal.LookupOptions{...})→mc.Queues.FromName(ctx, ..., &modal.QueueFromNameParams{...})modal.QueueEphemeral(ctx, &modal.EphemeralOptions{...})→mc.Queues.Ephemeral(ctx, &modal.QueueEphemeralParams{...})modal.QueueDelete(ctx, ..., &modal.DeleteOptions{...})→mc.Queues.Delete(ctx, ..., &modal.QueueDeleteParams{...})
queue.Clear(&modal.QueueClearOptions{...})→queue.Clear(ctx, &modal.QueueClearParams{...})queue.Get(&modal.QueueGetOptions{...})→queue.Get(ctx, &modal.QueueGetParams{...})queue.Put(..., &modal.QueuePutOptions{...})→queue.Put(ctx, ..., &modal.QueuePutParams{...})queue.Len(&modal.QueueLenOptions{...})→queue.Len(ctx, &modal.QueueLenParams{...})
Sandbox
Sandbox
app.CreateSandbox(image, &modal.SandboxOptions{...})→mc.Sandboxes.Create(ctx, app, image, &modal.SandboxCreateParams{...})modal.SandboxFromId(ctx, "sandbox-id")→mc.Sandboxes.FromID(ctx, "sandbox-id")modal.SandboxFromName(ctx, "app-name", "sandbox-name", &modal.SandboxFromNameOptions{...})→mc.Sandboxes.FromName(ctx, "app-name", "sandbox-name", &modal.SandboxFromNameParams{...})modal.SandboxList(ctx, &modal.SandboxListOptions{...})→mc.Sandboxes.List(ctx, &modal.SandboxListParams{...})
sandbox.Exec(..., modal.ExecOptions{...})→sandbox.Exec(ctx, ..., &modal.SandboxExecParams{...})sandbox.Terminate()→sandbox.Terminate(ctx)sandbox.Wait()→sandbox.Wait(ctx)
Secret
Secret
modal.SecretFromName(ctx, ..., &modal.SecretFromNameOptions{...})→mc.Secrets.FromName(ctx, ..., &modal.SecretFromNameParams{...})modal.SecretFromMap(ctx, ..., &modal.SecretFromMapOptions{...})→mc.Secrets.FromMap(ctx, ..., &modal.SecretFromMapParams{...})
Volume
Volume
modal.VolumeFromName(ctx, ..., &modal.VolumeFromNameOptions{...})→mc.Volumes.FromName(ctx, ..., &modal.VolumeFromNameParams{...})modal.VolumeEphemeral(ctx, &modal.EphemeralOptions{...})→mc.Volumes.Ephemeral(ctx, &modal.VolumeEphemeralParams{...})
Parameter name changes
Unit suffixes
Memory parameters now include explicit unit suffixes:memory→memoryMiBmemoryLimit→memoryLimitMiB
Getting help
If you encounter any issues during migration, please:- Check the updated examples in the JS examples and Go examples
- Reach out to Modal support for assistance