Skip to main content
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:
bl get applications
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:
bl get applications
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).
MemoryCPU cores
2048 MB1 core
4096 MB2 cores
8192 MB4 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.
Last modified on July 1, 2026