Applications are long-running deployed services that run your custom code as publicly accessible endpoints. They are ideal for web servers, APIs, dashboards, and any service that needs to be always-on.
Applications run on Blaxel’s mk3 micro-VM infrastructure and support revision management with canary traffic splitting, custom domain URLs, and deployment from source code, images, or forked sandboxes.
Application Runtime is currently in preview.
Key concepts
Application : A long-running deployment that serves traffic on a public URL.
Revision : An immutable snapshot of the application code, image, environment, and memory configuration. Each deploy creates a new revision (max 5 kept).
Traffic splitting : Route traffic between an active revision and a canary revision using percentage-based splitting.
Sticky sessions : Optional session affinity via stickySessionTtl to keep users on the same revision.
Custom URLs : Map verified custom domains to your application.
Create an application
Using the SDKs
import { ApplicationInstance } from "@blaxel/core" ;
const app = await ApplicationInstance . create ({
name: "my-app" ,
image: "my-registry/my-image:latest" ,
memory: 2048 ,
region: "us-pdx-1" ,
envs: [{ name: "NODE_ENV" , value: "production" }],
});
import asyncio
from blaxel.core import ApplicationInstance
async def main ():
app = await ApplicationInstance.create({
"name" : "my-app" ,
"image" : "my-registry/my-image:latest" ,
"memory" : 2048 ,
"region" : "us-pdx-1" ,
"envs" : [{ "name" : "NODE_ENV" , "value" : "production" }],
})
if __name__ == "__main__" :
asyncio.run(main())
import blaxel " github.com/blaxel-ai/sdk-go "
app , err := client . Applications . Create ( ctx , blaxel . ApplicationCreateParams {
Body : blaxel . Application {
Metadata : blaxel . Metadata { Name : "my-app" },
Spec : blaxel . ApplicationSpec {
Enabled : true ,
Region : "us-pdx-1" ,
Revisions : [] blaxel . AppRevision {{
Image : "my-registry/my-image:latest" ,
Memory : 2048 ,
Envs : [] blaxel . Env {{ Name : "NODE_ENV" , Value : "production" }},
}},
},
},
})
Using the CLI
Deploy from a project directory containing a blaxel.toml:
bl deploy --type application
Example blaxel.toml:
name = "my-app"
type = "application"
workspace = "my-workspace"
[ env ]
NODE_ENV = "production"
[ deploy ]
region = "us-pdx-1"
memory = 2048
To deploy a pre-built image, set the image field:
name = "my-app"
type = "application"
workspace = "my-workspace"
image = "my-registry/my-image:latest"
Using the HTTP API
curl -X POST https://api.blaxel.ai/v0/applications \
-H "Authorization: Bearer $BL_API_KEY " \
-H "X-Blaxel-Workspace: my-workspace" \
-H "Content-Type: application/json" \
-d '{
"metadata": { "name": "my-app" },
"spec": {
"enabled": true,
"region": "us-pdx-1",
"revisions": [{
"image": "my-registry/my-image:latest",
"memory": 2048,
"envs": [{ "name": "NODE_ENV", "value": "production" }]
}]
}
}'
Retrieve an application
import { ApplicationInstance } from "@blaxel/core" ;
const app = await ApplicationInstance . get ( "my-app" );
console . log ( app . status );
from blaxel.core import ApplicationInstance
app = await ApplicationInstance.get( "my-app" )
print (app.status)
app , err := client . Applications . Get ( ctx , "my-app" , blaxel . ApplicationGetParams {})
CLI:
HTTP API:
curl https://api.blaxel.ai/v0/applications/my-app \
-H "Authorization: Bearer $BL_API_KEY " \
-H "X-Blaxel-Workspace: my-workspace"
List applications
import { ApplicationInstance } from "@blaxel/core" ;
const apps = await ApplicationInstance . list ();
from blaxel.core import ApplicationInstance
apps = await ApplicationInstance.list()
apps , err := client . Applications . List ( ctx , blaxel . ApplicationListParams {})
CLI:
HTTP API:
curl https://api.blaxel.ai/v0/applications \
-H "Authorization: Bearer $BL_API_KEY " \
-H "X-Blaxel-Workspace: my-workspace"
Update an application
Updating an application with a new image or configuration creates a new revision.
import { ApplicationInstance } from "@blaxel/core" ;
const app = await ApplicationInstance . get ( "my-app" );
const updated = await app . update ({
image: "my-registry/my-image:v2" ,
memory: 4096 ,
});
from blaxel.core import ApplicationInstance
app = await ApplicationInstance.get( "my-app" )
updated = await app.update({
"image" : "my-registry/my-image:v2" ,
"memory" : 4096 ,
})
updated , err := client . Applications . Update ( ctx , "my-app" , blaxel . ApplicationUpdateParams {
Body : blaxel . Application {
Metadata : blaxel . Metadata { Name : "my-app" },
Spec : blaxel . ApplicationSpec {
Enabled : true ,
Region : "us-pdx-1" ,
Revisions : [] blaxel . AppRevision {{
Image : "my-registry/my-image:v2" ,
Memory : 4096 ,
}},
},
},
})
HTTP API:
curl -X PUT https://api.blaxel.ai/v0/applications/my-app \
-H "Authorization: Bearer $BL_API_KEY " \
-H "X-Blaxel-Workspace: my-workspace" \
-H "Content-Type: application/json" \
-d '{
"metadata": { "name": "my-app" },
"spec": {
"enabled": true,
"region": "us-pdx-1",
"revisions": [{
"image": "my-registry/my-image:v2",
"memory": 4096
}]
}
}'
Delete an application
import { ApplicationInstance } from "@blaxel/core" ;
await ApplicationInstance . delete ( "my-app" );
from blaxel.core import ApplicationInstance
await ApplicationInstance.delete( "my-app" )
err := client . Applications . Delete ( ctx , "my-app" )
CLI:
bl delete application my-app
HTTP API:
curl -X DELETE https://api.blaxel.ai/v0/applications/my-app \
-H "Authorization: Bearer $BL_API_KEY " \
-H "X-Blaxel-Workspace: my-workspace"
Revisions
Each deploy creates a new revision. A maximum of 5 revisions are kept per application. Revisions contain the image, environment variables, memory allocation, and port configuration.
List revisions
import { ApplicationInstance } from "@blaxel/core" ;
const app = await ApplicationInstance . get ( "my-app" );
const revisions = await app . listRevisions ();
from blaxel.core import ApplicationInstance
app = await ApplicationInstance.get( "my-app" )
revisions = await app.list_revisions()
revisions , err := client . Applications . ListRevisions ( ctx , "my-app" )
HTTP API:
curl https://api.blaxel.ai/v0/applications/my-app/revisions \
-H "Authorization: Bearer $BL_API_KEY " \
-H "X-Blaxel-Workspace: my-workspace"
Traffic splitting
Control how traffic is distributed between revisions using the traffic parameter on deploy:
traffic=100 (default): the new revision receives 100% of traffic (full deployment).
traffic=1-99: canary deployment. The new revision receives this percentage, and the active revision receives the rest.
traffic=0: staging deployment. The new revision is deployed but receives no traffic.
To deploy a canary revision via the HTTP API:
curl -X PUT https://api.blaxel.ai/v0/applications/my-app \
-H "Authorization: Bearer $BL_API_KEY " \
-H "X-Blaxel-Workspace: my-workspace" \
-H "Content-Type: application/json" \
-d '{
"metadata": { "name": "my-app" },
"spec": {
"enabled": true,
"region": "us-pdx-1",
"revision": {
"traffic": 20
},
"revisions": [{
"image": "my-registry/my-image:v3",
"memory": 2048
}]
}
}'
Sticky sessions
Enable sticky sessions to keep users routed to the same revision for the duration of the TTL:
{
"spec" : {
"revision" : {
"stickySessionTtl" : 3600
}
}
}
Setting stickySessionTtl to 0 disables sticky sessions.
Custom URLs
By default, applications are accessible at a generated URL. You can configure custom URLs using verified custom domains in your workspace.
Create or update an application with custom URLs
Pass the urls field in the application spec to attach a verified custom domain.
import { ApplicationInstance } from "@blaxel/core" ;
const app = await ApplicationInstance . create ({
metadata: {
name: "my-app" ,
},
spec: {
enabled: true ,
region: "us-pdx-1" ,
urls: [{ domain: "app.example.com" }],
revisions: [{
image: "my-registry/my-image:latest" ,
memory: 2048 ,
}],
},
});
from blaxel.core import ApplicationInstance
app = await ApplicationInstance.create({
"metadata" : { "name" : "my-app" },
"spec" : {
"enabled" : True ,
"region" : "us-pdx-1" ,
"urls" : [{ "domain" : "app.example.com" }],
"revisions" : [{
"image" : "my-registry/my-image:latest" ,
"memory" : 2048 ,
}],
},
})
app , err := client . Applications . Create ( ctx , blaxel . ApplicationCreateParams {
Body : blaxel . Application {
Metadata : blaxel . Metadata { Name : "my-app" },
Spec : blaxel . ApplicationSpec {
Enabled : true ,
Region : "us-pdx-1" ,
Urls : [] blaxel . AppUrl {{ Domain : "app.example.com" }},
Revisions : [] blaxel . AppRevision {{
Image : "my-registry/my-image:latest" ,
Memory : 2048 ,
}},
},
},
})
To add a custom URL to an existing application, use update:
import { ApplicationInstance } from "@blaxel/core" ;
const app = await ApplicationInstance . get ( "my-app" );
const updated = await ApplicationInstance . update ( "my-app" , {
metadata: app . metadata ,
spec: {
... app . spec ,
urls: [{ domain: "app.example.com" }],
},
});
from blaxel.core import ApplicationInstance
app = await ApplicationInstance.get( "my-app" )
updated = await app.update({
"metadata" : app.metadata,
"spec" : {
** app.spec,
"urls" : [{ "domain" : "app.example.com" }],
},
})
updated , err := client . Applications . Update ( ctx , "my-app" , blaxel . ApplicationUpdateParams {
Body : blaxel . Application {
Metadata : existing . Metadata ,
Spec : blaxel . ApplicationSpec {
Enabled : existing . Spec . Enabled ,
Region : existing . Spec . Region ,
Urls : [] blaxel . AppUrl {{ Domain : "app.example.com" }},
Revisions : existing . Spec . Revisions ,
},
},
})
HTTP API:
curl -X PUT https://api.blaxel.ai/v0/applications/my-app \
-H "Authorization: Bearer $BL_API_KEY " \
-H "X-Blaxel-Workspace: my-workspace" \
-H "Content-Type: application/json" \
-d '{
"metadata": { "name": "my-app" },
"spec": {
"enabled": true,
"region": "us-pdx-1",
"urls": [
{ "domain": "app.example.com" }
],
"revisions": [{
"image": "my-registry/my-image:latest",
"memory": 2048
}]
}
}'
For wildcard custom domains (e.g. *.sandbox.example.com), use the subdomain field:
{
"spec" : {
"urls" : [
{ "subdomain" : "myapp" , "domain" : "sandbox.example.com" }
]
}
}
Create a custom domain for an application
You can also create a custom domain scoped to a specific application using the dedicated endpoint. After creation, configure DNS records and verify domain ownership before it becomes active.
curl -X POST https://api.blaxel.ai/v0/applications/my-app/customdomains \
-H "Authorization: Bearer $BL_API_KEY " \
-H "X-Blaxel-Workspace: my-workspace" \
-H "Content-Type: application/json" \
-d '{
"metadata": { "name": "app.example.com" },
"spec": {
"type": "applications",
"domain": "app.example.com",
"region": "us-pdx-1"
}
}'
The domain must be a verified custom domain in your workspace. Custom domain verification is managed in the Infrastructure section of the Blaxel Console.
Environment variables and secrets
Pass environment variables to your application through the revision’s envs field. Each entry supports either a plain value or a reference to a Blaxel secretName.
{
"spec" : {
"revisions" : [{
"image" : "my-registry/my-image:latest" ,
"memory" : 2048 ,
"envs" : [
{ "name" : "DATABASE_URL" , "value" : "postgres://..." },
{ "name" : "API_KEY" , "secretName" : "my-api-key-secret" }
]
}]
}
}
Memory and compute
Memory allocation is set per revision in megabytes. The default is 2048 MB. CPU resources are allocated proportionally based on memory (CPU = memory / 2048 cores).
Memory CPU cores 2048 MB 1 core 4096 MB 2 cores 8192 MB 4 cores
Application deployment statuses
During the deployment process, the possible application statuses are:
DEPLOYING: The application deployment is in progress.
DEPLOYED: The application is running and serving traffic.
FAILED: An error occurred during the build or deployment.
Sandbox snapshots and fork Create snapshots and fork sandboxes into applications or new sandboxes.
Variables and secrets Manage environment variables and secrets for your deployments.