> ## Documentation Index
> Fetch the complete documentation index at: https://blaxel-cdrappier-devin-application-runtime-docs.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Applications

> Deploy long-running services as publicly accessible endpoints with revision management, canary traffic splitting, and custom URLs.

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.

<Note>
  Application Runtime is currently in preview.
</Note>

## 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

<CodeGroup>
  ```typescript TypeScript theme={null}
  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" }],
  });
  ```

  ```python Python theme={null}
  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())
  ```

  ```go Go theme={null}
  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"}},
              }},
          },
      },
  })
  ```
</CodeGroup>

### Using the CLI

Deploy from a project directory containing a `blaxel.toml`:

```bash theme={null}
bl deploy --type application
```

Example `blaxel.toml`:

```toml theme={null}
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:

```toml theme={null}
name = "my-app"
type = "application"
workspace = "my-workspace"
image = "my-registry/my-image:latest"
```

### Using the HTTP API

```bash theme={null}
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

<CodeGroup>
  ```typescript TypeScript theme={null}
  import { ApplicationInstance } from "@blaxel/core";

  const app = await ApplicationInstance.get("my-app");
  console.log(app.status);
  ```

  ```python Python theme={null}
  from blaxel.core import ApplicationInstance

  app = await ApplicationInstance.get("my-app")
  print(app.status)
  ```

  ```go Go theme={null}
  app, err := client.Applications.Get(ctx, "my-app", blaxel.ApplicationGetParams{})
  ```
</CodeGroup>

CLI:

```bash theme={null}
bl get applications
```

HTTP API:

```bash theme={null}
curl https://api.blaxel.ai/v0/applications/my-app \
  -H "Authorization: Bearer $BL_API_KEY" \
  -H "X-Blaxel-Workspace: my-workspace"
```

## List applications

<CodeGroup>
  ```typescript TypeScript theme={null}
  import { ApplicationInstance } from "@blaxel/core";

  const apps = await ApplicationInstance.list();
  ```

  ```python Python theme={null}
  from blaxel.core import ApplicationInstance

  apps = await ApplicationInstance.list()
  ```

  ```go Go theme={null}
  apps, err := client.Applications.List(ctx, blaxel.ApplicationListParams{})
  ```
</CodeGroup>

CLI:

```bash theme={null}
bl get applications
```

HTTP API:

```bash theme={null}
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.

<CodeGroup>
  ```typescript TypeScript theme={null}
  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,
  });
  ```

  ```python Python theme={null}
  from blaxel.core import ApplicationInstance

  app = await ApplicationInstance.get("my-app")
  updated = await app.update({
      "image": "my-registry/my-image:v2",
      "memory": 4096,
  })
  ```

  ```go Go theme={null}
  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,
              }},
          },
      },
  })
  ```
</CodeGroup>

HTTP API:

```bash theme={null}
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

<CodeGroup>
  ```typescript TypeScript theme={null}
  import { ApplicationInstance } from "@blaxel/core";

  await ApplicationInstance.delete("my-app");
  ```

  ```python Python theme={null}
  from blaxel.core import ApplicationInstance

  await ApplicationInstance.delete("my-app")
  ```

  ```go Go theme={null}
  err := client.Applications.Delete(ctx, "my-app")
  ```
</CodeGroup>

CLI:

```bash theme={null}
bl delete application my-app
```

HTTP API:

```bash theme={null}
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

<CodeGroup>
  ```typescript TypeScript theme={null}
  import { ApplicationInstance } from "@blaxel/core";

  const app = await ApplicationInstance.get("my-app");
  const revisions = await app.listRevisions();
  ```

  ```python Python theme={null}
  from blaxel.core import ApplicationInstance

  app = await ApplicationInstance.get("my-app")
  revisions = await app.list_revisions()
  ```

  ```go Go theme={null}
  revisions, err := client.Applications.ListRevisions(ctx, "my-app")
  ```
</CodeGroup>

HTTP API:

```bash theme={null}
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:

```bash theme={null}
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:

```json theme={null}
{
  "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.

<CodeGroup>
  ```typescript TypeScript theme={null}
  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,
      }],
    },
  });
  ```

  ```python Python theme={null}
  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,
          }],
      },
  })
  ```

  ```go Go theme={null}
  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,
              }},
          },
      },
  })
  ```
</CodeGroup>

To add a custom URL to an existing application, use update:

<CodeGroup>
  ```typescript TypeScript theme={null}
  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" }],
    },
  });
  ```

  ```python Python theme={null}
  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"}],
      },
  })
  ```

  ```go Go theme={null}
  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,
          },
      },
  })
  ```
</CodeGroup>

HTTP API:

```bash theme={null}
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:

```json theme={null}
{
  "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.

```bash theme={null}
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"
    }
  }'
```

<Note>
  The domain must be a verified custom domain in your workspace. Custom domain verification is managed in the [Infrastructure section](/Infrastructure/Custom-domains) of the Blaxel Console.
</Note>

## 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`.

```json theme={null}
{
  "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.

<CardGroup cols={2}>
  <Card title="Sandbox snapshots and fork" icon="code-fork" href="/Sandboxes/Snapshots-and-fork">
    Create snapshots and fork sandboxes into applications or new sandboxes.
  </Card>

  <Card title="Variables and secrets" icon="key" href="/Agents/Variables-and-secrets">
    Manage environment variables and secrets for your deployments.
  </Card>
</CardGroup>
