# Workload settings

A [workload](/en/documentation/platform/workloads/) is the object that receives traffic for a set of domains. It holds the domains, the infrastructure it runs on, the HTTP versions and ports, the TLS settings, and mTLS. A sub-object of the workload, the deployment, names the [application](/en/documentation/platform/applications/), the [firewall](/en/documentation/platform/firewall/), and the [custom page set](/en/documentation/platform/workloads/custom-pages/settings/) that serve that traffic. This page lists every field of both objects by its API name, with the Console control beside it. For the numeric bounds in one place, refer to [Workloads limits](/en/documentation/platform/workloads/limits/). For the path a request follows through these objects, refer to [How Workloads works](/en/documentation/platform/workloads/how-it-works/).

---

## Interfaces

Four interfaces write the same two objects. The tables on this page name the Console control, the API field, and the CLI flag of each field.

| Interface                                                    | Create                                                                                                                                                                                  | Read, update, delete                                                                                                                                                                                                                                                                        |
| ------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [Azion Console](https://console.azion.com/)                  | The **Workloads** menu, then the **Create Workload** page at `/workloads/create`, with the sections **Infrastructure**, **Domains**, **Protocol Settings**, and **Deployment Settings** | The **Edit Workload** page holds the same sections; its **Deployment Settings** section edits the deployment                                                                                                                                                                                |
| Azion API v4                                                 | `POST /v4/workspace/workloads`; `POST /v4/workspace/workloads/{workload_id}/deployments` for the deployment                                                                             | `GET`, `PUT`, `PATCH`, and `DELETE /v4/workspace/workloads/{workload_id}`; `GET /v4/workspace/workloads` lists them. `GET /v4/workspace/workloads/{workload_id}/deployments` lists the deployment, and `PATCH /v4/workspace/workloads/{workload_id}/deployments/{deployment_id}` changes it |
| Azion CLI                                                    | [`azion create workload`](/en/documentation/devtools/cli/resources/) and `azion create workload-deployment`                                                                             | `azion describe workload`, `azion update workload --file`, and `azion list workload-deployment`                                                                                                                                                                                             |
| [Terraform](/en/documentation/devtools/terraform/workloads/) | The `azion_workload` and `azion_workload_deployment` resources                                                                                                                          | The same resources                                                                                                                                                                                                                                                                          |

`azion create workload` sets `name` and `active` from flags; every other workload field goes in the JSON file of `--file`. `azion update workload --file` reads the workload ID from an `"id"` key inside that file. The CLI has no command that updates or deletes a deployment. Change a deployment's application, firewall, or custom page set in the Console or with the API `PATCH`.

On API v3, the protocol and TLS settings of this page lived in an application's [Main Settings](/en/documentation/platform/applications/main-settings-v3/). On API v4 they belong to the workload. For the full mapping between the two models, refer to [API v4 Migration](/en/documentation/fundamentals/api-v4-migration/).

---

## General

The general fields identify the workload and record who changed it. The API requires `name` and nothing else. Every other field in this table is read-only, except `active`.

| API field         | Type              | Values                                                         | Default              | CLI flag                                     |
| ----------------- | ----------------- | -------------------------------------------------------------- | -------------------- | -------------------------------------------- |
| `id`              | integer           | assigned by Azion, read-only                                   | none                 | none                                         |
| `name`            | string            | 1 to 100 characters                                            | required, no default | `--name` on `create`; `--file` on `update`   |
| `active`          | boolean           | `true`, `false`                                                | `true`               | `--active` on `create`; `--file` on `update` |
| `last_editor`     | string            | the email of the last user who changed the workload, read-only | none                 | none                                         |
| `last_modified`   | string, date-time | read-only                                                      | none                 | none                                         |
| `created_at`      | string, date-time | read-only                                                      | none                 | none                                         |
| `product_version` | string            | read-only                                                      | `1.0`                | none                                         |

The `name` labels the workload in your account and is not a domain address, so you can change it at any time. A name of 101 characters or more is refused with `Ensure this field has no more than 100 characters.`

---

## Infrastructure

The `infrastructure` field chooses the network that serves the workload and the suffix of its workload domain. In the Console, the **Infrastructure** section reads: "Select the infrastructure type for your Workload. Once this option is saved, it cannot be modified."

| Console control           | API field        | Type    | Values                                                                                 | Default | CLI flag      |
| ------------------------- | ---------------- | ------- | -------------------------------------------------------------------------------------- | ------- | ------------- |
| **Infrastructure** radios | `infrastructure` | integer | *Production Infrastructure (All Edge Locations)* (`1`), *Staging Infrastructure* (`2`) | `1`     | `--file` only |

The two values differ in where the workload runs and in the domains it accepts:

| Value | Network                                                    | Workload domain              | Custom domains                                                                               |
| ----- | ---------------------------------------------------------- | ---------------------------- | -------------------------------------------------------------------------------------------- |
| `1`   | The Production Network, for global availability            | `<id>.map.azionedge.net`     | Accepted in `domains`                                                                        |
| `2`   | The Staging Network, for testing, with limited propagation | `<id>.preview.azionedge.net` | Refused with `Custom hostname is not available in the environment 'Staging Infrastructure'.` |

A staging workload is reached only through its workload domain, and changes made to it do not affect the production workload. The value is fixed at creation: an update that changes it is refused with `The infrastructure cannot be changed after Workload creation.` For example, to move a configuration tested on staging to production, you create a second workload with `infrastructure` set to `1` instead of editing the first.

---

## Domains

The domain fields decide which hostnames the workload answers. Every workload gets a read-only workload domain, and `domains` adds your own hostnames and the optional free `azion.app` hostname that the Console calls **Azion Custom Domain**. The Console section **Domains** writes all three fields.

| Console control                                                                                                                                                                | API field                      | Type            | Values                                                                                     | Default              | CLI flag      |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------ | --------------- | ------------------------------------------------------------------------------------------ | -------------------- | ------------- |
| **Subdomain** and **Domain**, one row per hostname, added with **Add Domain**; the **Custom Domain** switch and the **Azion Custom Domain** field for the `azion.app` hostname | `domains`                      | array of string | hostnames that conform to RFC 1035, wildcards excluded                                     | `[]`                 | `--file` only |
| **Workload Domain**                                                                                                                                                            | `workload_domain`              | string          | `<id>.map.azionedge.net` on production, `<id>.preview.azionedge.net` on staging, read-only | assigned at creation | none          |
| **Workload Domain Allow Access** switch                                                                                                                                        | `workload_domain_allow_access` | boolean         | `true`, `false`                                                                            | `true`               | `--file` only |

The **Domain** field takes a domain you type or one you select from [Edge DNS](/en/documentation/platform/edge-dns/). The **Azion Custom Domain** field takes a name such as `my-custom-name` and appends `.azion.app`, and the full hostname is stored in `domains` beside your own. The `azion.app` hostname is available at no additional cost.

`workload_domain_allow_access` set to `true` lets clients reach the workload on its workload domain, whatever else `domains` holds. Set it to `false` when the workload must answer only on your own hostnames. To point your own domain at the workload domain, refer to [Point a domain to a workload](/en/documentation/guides/platform/migration/point-domain-to-azion/).

The API applies these rules to `domains`:

| Rule                                                                                               | Refused with                                                                                        |
| -------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- |
| The account must have permission to use every domain in the list                                   | `This account is not allowed to use the following CNAMEs: example.com.`                             |
| A workload holds at most one `azion.app` hostname, whether the two entries repeat a name or differ | `Duplicated usage of suffix in alternate_domains: 'azion.app'.`                                     |
| An `azion.app` hostname that another workload holds is not available                               | `The custom hostname is not available.`                                                             |
| Every entry conforms to RFC 1035, so a wildcard such as `*.azion.app` is refused                   | `The domain does not conform to the format defined in RFC 1035.`                                    |
| A staging workload takes no custom hostname                                                        | `Custom hostname is not available in the environment 'Staging Infrastructure'.`                     |
| With `workload_domain_allow_access` set to `false`, `domains` must hold at least one hostname      | `When the workload hostname access is blocked, the workload requires alternate domains or domains.` |

The API stores each hostname with the case you send: `Docs-Rework-Upper.azion.app` reads back unchanged.

---

## Protocols and ports

The `protocols.http` object sets the HTTP versions the workload accepts and the ports it listens on. In the Console, the **Protocol Settings** section writes it, through two switches and three port lists.

| Console control                                                    | API field                    | Type                                          | Values                                                                                        | Default                       | CLI flag      |
| ------------------------------------------------------------------ | ---------------------------- | --------------------------------------------- | --------------------------------------------------------------------------------------------- | ----------------------------- | ------------- |
| **HTTP/3 support** switch for `http3`                              | `protocols.http.versions`    | array of string, at most 3 items              | `http1`, `http2`, `http3`                                                                     | `["http1", "http2", "http3"]` | `--file` only |
| **HTTP Ports**                                                     | `protocols.http.http_ports`  | array of integer, 1 to 4 items                | `80`, `8008`, `8080`, `8880`                                                                  | `[80]`                        | `--file` only |
| **HTTPS Ports**, available when the **HTTPS support** switch is on | `protocols.http.https_ports` | array of integer, 1 to 12 items, or `null`    | `443`, `8443`, `9440`, `9441`, `9442`, `9443`, `7777`, `8888`, `9553`, `9653`, `8035`, `8090` | `[443]`                       | `--file` only |
| **HTTP3 Port**, available when the **HTTP/3 support** switch is on | `protocols.http.quic_ports`  | array of integer, at most 12 items, or `null` | port numbers; `443` and `8443` are accepted                                                   | `[443]`                       | `--file` only |

HTTP/3 runs over QUIC. The Console help text for **HTTP/3 support** reads "Enable HTTP/3 over QUIC. Requires HTTPS support to be enabled.", and the API adds a second dependency on `versions`: a list with `http3` must also hold `http1` and `http2`. Otherwise the API refuses it with `Missing required choices for multiple choices field: ['http1', 'http2'].`

An HTTP port outside the four values is refused with `Invalid choices for multiple choices field: [80, 8008, 8080, 8880].` For example, a workload that serves HTTP on `8080` alongside `80` sends `"http_ports": [80, 8080]`. For the delivery and origin port combinations an application can use, refer to [Configure HTTP and HTTPS ports](/en/documentation/guides/application-development/getting-started/configure-ports/).

---

## TLS

Transport Layer Security (TLS) encrypts the connection between a client and the workload. The `tls` object names the certificate the workload presents, the lowest TLS version it accepts, and the cipher suite it offers. In the Console, these controls sit in the **Protocol Settings** section, and **Digital Certificate** appears when the **HTTPS support** switch is on.

| Console control         | API field             | Type               | Values                                                                                                     | Default   | CLI flag      |
| ----------------------- | --------------------- | ------------------ | ---------------------------------------------------------------------------------------------------------- | --------- | ------------- |
| **Digital Certificate** | `tls.certificate`     | integer, or `null` | the ID of a certificate of type `edge_certificate`, or `null` for the Azion SAN certificate                | `null`    | `--file` only |
| **Minimum TLS version** | `tls.minimum_version` | enum               | `tls_1_0` (TLS 1.0, deprecated), `tls_1_1` (TLS 1.1, deprecated), `tls_1_2` (TLS 1.2), `tls_1_3` (TLS 1.3) | `tls_1_3` | `--file` only |
| **Cipher suite**        | `tls.ciphers`         | integer            | `1` to `8`, one per suite in Cipher suites                                                                 | `7`       | `--file` only |

HTTPS needs an X.509 certificate. You can upload your own certificate to [Certificate Manager](/en/documentation/platform/workloads/certificate-manager/certificates/) or request a Let's Encrypt certificate that Azion manages, both at no additional cost. With `tls.certificate` set to `null`, the workload presents the Azion SAN certificate, which covers the Azion Custom Domain and the workload domain. A certificate of another type is refused: a Trusted CA certificate in `tls.certificate` returns `Invalid certificate type, MUST be an Edge Certificate.`

`tls.minimum_version` sets a floor, not the exact version a session uses. A workload with `tls_1_2` can still serve a session over TLS 1.3, depending on the cipher the client and the workload negotiate from the suite. Azion blocks TLS renegotiation and TLS resumption by default. To change that, contact the Sales team.

The cipher suite decides which cryptographic algorithms a TLS connection may use. The client and the workload negotiate one cipher from the suite for each session. The API refuses a value outside `1` to `8`. For `9`, the message is `"9" is not a valid choice.` To change the suite step by step, refer to [Set the TLS cipher suite](/en/documentation/guides/application-security/tls-and-certificates/ciphers/).

### Cipher suites

Each value of `tls.ciphers` selects one named suite. The tables below list the ciphers each suite holds, with the TLS version each cipher belongs to.

#### Suite 1, TLSv1.2\_2018

`ciphers: 1` selects `TLSv1.2_2018`, which holds three TLS 1.3 ciphers and 13 TLS 1.2 ciphers:

| TLS version | Cipher                          |
| ----------- | ------------------------------- |
| TLS 1.3     | `TLS_AES_256_GCM_SHA384`        |
| TLS 1.3     | `TLS_CHACHA20_POLY1305_SHA256`  |
| TLS 1.3     | `TLS_AES_128_GCM_SHA256`        |
| TLS 1.2     | `ECDHE-ECDSA-AES256-GCM-SHA384` |
| TLS 1.2     | `ECDHE-RSA-AES256-GCM-SHA384`   |
| TLS 1.2     | `ECDHE-ECDSA-CHACHA20-POLY1305` |
| TLS 1.2     | `ECDHE-RSA-CHACHA20-POLY1305`   |
| TLS 1.2     | `ECDHE-ECDSA-AES128-GCM-SHA256` |
| TLS 1.2     | `ECDHE-RSA-AES128-GCM-SHA256`   |
| TLS 1.2     | `ECDHE-ECDSA-AES256-SHA384`     |
| TLS 1.2     | `ECDHE-RSA-AES256-SHA384`       |
| TLS 1.2     | `ECDHE-ECDSA-AES128-SHA256`     |
| TLS 1.2     | `ECDHE-RSA-AES128-SHA256`       |
| TLS 1.2     | `AES256-GCM-SHA384`             |
| TLS 1.2     | `AES128-GCM-SHA256`             |
| TLS 1.2     | `AES128-SHA256`                 |

#### Suite 2, TLSv1.2\_2019

`ciphers: 2` selects `TLSv1.2_2019`, which holds three TLS 1.3 ciphers and 10 TLS 1.2 ciphers:

| TLS version | Cipher                          |
| ----------- | ------------------------------- |
| TLS 1.3     | `TLS_AES_256_GCM_SHA384`        |
| TLS 1.3     | `TLS_CHACHA20_POLY1305_SHA256`  |
| TLS 1.3     | `TLS_AES_128_GCM_SHA256`        |
| TLS 1.2     | `ECDHE-ECDSA-AES256-GCM-SHA384` |
| TLS 1.2     | `ECDHE-RSA-AES256-GCM-SHA384`   |
| TLS 1.2     | `ECDHE-ECDSA-CHACHA20-POLY1305` |
| TLS 1.2     | `ECDHE-RSA-CHACHA20-POLY1305`   |
| TLS 1.2     | `ECDHE-ECDSA-AES128-GCM-SHA256` |
| TLS 1.2     | `ECDHE-RSA-AES128-GCM-SHA256`   |
| TLS 1.2     | `ECDHE-ECDSA-AES256-SHA384`     |
| TLS 1.2     | `ECDHE-RSA-AES256-SHA384`       |
| TLS 1.2     | `ECDHE-ECDSA-AES128-SHA256`     |
| TLS 1.2     | `ECDHE-RSA-AES128-SHA256`       |

#### Suite 3, TLSv1.3\_2022

`ciphers: 3` selects `TLSv1.3_2022`, which holds six TLS 1.2 ciphers:

| TLS version | Cipher                          |
| ----------- | ------------------------------- |
| TLS 1.2     | `ECDHE-ECDSA-AES256-GCM-SHA384` |
| TLS 1.2     | `ECDHE-RSA-AES256-GCM-SHA384`   |
| TLS 1.2     | `ECDHE-ECDSA-CHACHA20-POLY1305` |
| TLS 1.2     | `ECDHE-RSA-CHACHA20-POLY1305`   |
| TLS 1.2     | `ECDHE-ECDSA-AES128-GCM-SHA256` |
| TLS 1.2     | `ECDHE-RSA-AES128-GCM-SHA256`   |

#### Suite 4, TLSv1.2\_2021

`ciphers: 4` selects `TLSv1.2_2021`, which holds three TLS 1.3 ciphers and six TLS 1.2 ciphers:

| TLS version | Cipher                          |
| ----------- | ------------------------------- |
| TLS 1.3     | `TLS_AES_256_GCM_SHA384`        |
| TLS 1.3     | `TLS_CHACHA20_POLY1305_SHA256`  |
| TLS 1.3     | `TLS_AES_128_GCM_SHA256`        |
| TLS 1.2     | `ECDHE-ECDSA-AES256-GCM-SHA384` |
| TLS 1.2     | `ECDHE-RSA-AES256-GCM-SHA384`   |
| TLS 1.2     | `ECDHE-ECDSA-CHACHA20-POLY1305` |
| TLS 1.2     | `ECDHE-RSA-CHACHA20-POLY1305`   |
| TLS 1.2     | `ECDHE-ECDSA-AES128-GCM-SHA256` |
| TLS 1.2     | `ECDHE-RSA-AES128-GCM-SHA256`   |

#### Suite 5, Legacy\_v2025Q1

`ciphers: 5` selects `Legacy_v2025Q1`, which holds three TLS 1.3 ciphers and 15 TLS 1.2 ciphers:

| TLS version | Cipher                          |
| ----------- | ------------------------------- |
| TLS 1.3     | `TLS_AES_256_GCM_SHA384`        |
| TLS 1.3     | `TLS_CHACHA20_POLY1305_SHA256`  |
| TLS 1.3     | `TLS_AES_128_GCM_SHA256`        |
| TLS 1.2     | `ECDHE-ECDSA-AES256-GCM-SHA384` |
| TLS 1.2     | `ECDHE-RSA-AES256-GCM-SHA384`   |
| TLS 1.2     | `ECDHE-ECDSA-CHACHA20-POLY1305` |
| TLS 1.2     | `ECDHE-RSA-CHACHA20-POLY1305`   |
| TLS 1.2     | `ECDHE-ECDSA-AES128-GCM-SHA256` |
| TLS 1.2     | `ECDHE-RSA-AES128-GCM-SHA256`   |
| TLS 1.2     | `ECDHE-ECDSA-AES256-SHA384`     |
| TLS 1.2     | `ECDHE-RSA-AES256-SHA384`       |
| TLS 1.2     | `ECDHE-ECDSA-AES128-SHA256`     |
| TLS 1.2     | `ECDHE-RSA-AES128-SHA256`       |
| TLS 1.2     | `AES256-GCM-SHA384`             |
| TLS 1.2     | `AES128-GCM-SHA256`             |
| TLS 1.2     | `AES256-SHA`                    |
| TLS 1.2     | `AES128-SHA256`                 |
| TLS 1.2     | `AES128-SHA`                    |

#### Suite 6, Compatible\_v2025Q1

`ciphers: 6` selects `Compatible_v2025Q1`, which holds three TLS 1.3 ciphers and 12 TLS 1.2 ciphers:

| TLS version | Cipher                          |
| ----------- | ------------------------------- |
| TLS 1.3     | `TLS_AES_256_GCM_SHA384`        |
| TLS 1.3     | `TLS_CHACHA20_POLY1305_SHA256`  |
| TLS 1.3     | `TLS_AES_128_GCM_SHA256`        |
| TLS 1.2     | `ECDHE-ECDSA-AES256-GCM-SHA384` |
| TLS 1.2     | `ECDHE-RSA-AES256-GCM-SHA384`   |
| TLS 1.2     | `ECDHE-ECDSA-CHACHA20-POLY1305` |
| TLS 1.2     | `ECDHE-RSA-CHACHA20-POLY1305`   |
| TLS 1.2     | `ECDHE-ECDSA-AES128-GCM-SHA256` |
| TLS 1.2     | `ECDHE-RSA-AES128-GCM-SHA256`   |
| TLS 1.2     | `ECDHE-ECDSA-AES256-SHA384`     |
| TLS 1.2     | `ECDHE-RSA-AES256-SHA384`       |
| TLS 1.2     | `ECDHE-ECDSA-AES128-SHA256`     |
| TLS 1.2     | `ECDHE-RSA-AES128-SHA256`       |
| TLS 1.2     | `AES256-GCM-SHA384`             |
| TLS 1.2     | `AES128-GCM-SHA256`             |

#### Suite 7, Modern\_v2025Q1

`ciphers: 7` selects `Modern_v2025Q1`, which holds three TLS 1.3 ciphers and six TLS 1.2 ciphers:

| TLS version | Cipher                          |
| ----------- | ------------------------------- |
| TLS 1.3     | `TLS_AES_256_GCM_SHA384`        |
| TLS 1.3     | `TLS_CHACHA20_POLY1305_SHA256`  |
| TLS 1.3     | `TLS_AES_128_GCM_SHA256`        |
| TLS 1.2     | `ECDHE-ECDSA-AES256-GCM-SHA384` |
| TLS 1.2     | `ECDHE-RSA-AES256-GCM-SHA384`   |
| TLS 1.2     | `ECDHE-ECDSA-CHACHA20-POLY1305` |
| TLS 1.2     | `ECDHE-RSA-CHACHA20-POLY1305`   |
| TLS 1.2     | `ECDHE-ECDSA-AES128-GCM-SHA256` |
| TLS 1.2     | `ECDHE-RSA-AES128-GCM-SHA256`   |

#### Suite 8, Legacy\_v2017Q1

`ciphers: 8` selects `Legacy_v2017Q1`, which holds three TLS 1.3 ciphers and 26 TLS 1.2 ciphers:

| TLS version | Cipher                          |
| ----------- | ------------------------------- |
| TLS 1.3     | `TLS_AES_256_GCM_SHA384`        |
| TLS 1.3     | `TLS_CHACHA20_POLY1305_SHA256`  |
| TLS 1.3     | `TLS_AES_128_GCM_SHA256`        |
| TLS 1.2     | `ECDHE-ECDSA-AES256-GCM-SHA384` |
| TLS 1.2     | `ECDHE-RSA-AES256-GCM-SHA384`   |
| TLS 1.2     | `ECDHE-ECDSA-AES128-GCM-SHA256` |
| TLS 1.2     | `ECDHE-RSA-AES128-GCM-SHA256`   |
| TLS 1.2     | `ECDHE-ECDSA-AES256-SHA384`     |
| TLS 1.2     | `ECDHE-RSA-AES256-SHA384`       |
| TLS 1.2     | `ECDHE-ECDSA-AES128-SHA256`     |
| TLS 1.2     | `ECDHE-RSA-AES128-SHA256`       |
| TLS 1.2     | `ECDHE-ECDSA-AES256-SHA`        |
| TLS 1.2     | `ECDHE-ECDSA-AES128-SHA`        |
| TLS 1.2     | `ECDHE-RSA-AES256-SHA`          |
| TLS 1.2     | `ECDHE-RSA-AES128-SHA`          |
| TLS 1.2     | `ECDHE-ECDSA-AES256-CCM`        |
| TLS 1.2     | `ECDHE-ECDSA-AES256-CCM8`       |
| TLS 1.2     | `ECDHE-ECDSA-AES128-CCM`        |
| TLS 1.2     | `ECDHE-ECDSA-AES128-CCM8`       |
| TLS 1.2     | `AES256-GCM-SHA384`             |
| TLS 1.2     | `AES128-GCM-SHA256`             |
| TLS 1.2     | `AES256-SHA256`                 |
| TLS 1.2     | `AES256-SHA`                    |
| TLS 1.2     | `AES128-SHA256`                 |
| TLS 1.2     | `AES128-SHA`                    |
| TLS 1.2     | `AES256-CCM`                    |
| TLS 1.2     | `AES256-CCM8`                   |
| TLS 1.2     | `AES128-CCM`                    |
| TLS 1.2     | `AES128-CCM8`                   |

---

## mTLS

Mutual TLS (mTLS) makes the client present a certificate too, and the workload checks it against a certificate authority you trust. The `mtls` object turns the check on and names the Trusted CA certificate and the certificate revocation lists (CRLs) it uses. Set it through the API or the JSON file of `azion update workload --file`.

| API field                  | Type                                           | Values                                                   | Default | CLI flag      |
| -------------------------- | ---------------------------------------------- | -------------------------------------------------------- | ------- | ------------- |
| `mtls.enabled`             | boolean                                        | `true`, `false`                                          | `false` | `--file` only |
| `mtls.config.certificate`  | integer, or `null`                             | the ID of a certificate of type `trusted_ca_certificate` | `null`  | `--file` only |
| `mtls.config.crl`          | array of integer, at most 100 items, or `null` | CRL IDs                                                  | `null`  | `--file` only |
| `mtls.config.verification` | enum, or `null`                                | `enforce`, `permissive`                                  | `null`  | `--file` only |

A server certificate in `mtls.config.certificate` is refused with `Invalid certificate type, MUST be a Trusted CA.` For example, a workload that checks client certificates against your CA and one CRL, in `enforce` mode, sends `"mtls": {"enabled": true, "config": {"certificate": <trusted-ca-id>, "crl": [<crl-id>], "verification": "enforce"}}`. For how `enforce` and `permissive` treat a client certificate, refer to [mTLS](/en/documentation/platform/workloads/mtls/).

---

## Deployment

A deployment binds the application, the firewall, and the custom page set that serve a workload's traffic. It is a sub-resource of the workload, at `/v4/workspace/workloads/{workload_id}/deployments`, and a workload holds one deployment. A second one is refused with `The maximum number of deployments allowed per workload is 1.` In the Console, the **Deployment Settings** section of the workload writes it.

| Console control | API field                         | Type               | Values                                                 | CLI flag           |
| --------------- | --------------------------------- | ------------------ | ------------------------------------------------------ | ------------------ |
| none            | `name`                            | string             | the deployment's name                                  | `--name`           |
| none            | `active`                          | boolean            | `true`, `false`                                        | `--active`         |
| none            | `current`                         | boolean            | `true` makes this deployment the one the workload runs | `--current`        |
| none            | `strategy.type`                   | string             | `default`                                              | `--strategy-type`  |
| **Application** | `strategy.attributes.application` | integer            | the ID of an application                               | `--application-id` |
| **Firewall**    | `strategy.attributes.firewall`    | integer            | the ID of a firewall                                   | `--firewall-id`    |
| **Custom Page** | `strategy.attributes.custom_page` | integer, or `null` | the ID of a custom page set                            | `--custom-page`    |

`strategy.attributes` holds exactly these three keys. A deployment created without a custom page set reads `"custom_page": null`. A deployment without a firewall shows *Select a Firewall* in the Console **Firewall** field and `0` in `azion list workload-deployment --details`. A custom page set takes effect only when the deployment names it in `custom_page`. A workload that still uses a firewall keeps that firewall from being deleted, and deleting the deployment does not release it: delete the workload first.

---

## Request body

The JSON body below creates a staging workload with TLS 1.2 as the floor, cipher suite 4, and two HTTP and two HTTPS ports. The same body works for `POST /v4/workspace/workloads` and for the file of `azion create workload --file`:

```json
{
  "name": "my-workload",
  "active": true,
  "infrastructure": 2,
  "tls": { "certificate": null, "ciphers": 4, "minimum_version": "tls_1_2" },
  "protocols": { "http": { "versions": ["http1", "http2"], "http_ports": [80, 8080], "https_ports": [443, 8443], "quic_ports": null } },
  "domains": [],
  "workload_domain_allow_access": true
}
```

Send it with the CLI, with the body saved as `wl-staging.json`:

```bash
azion create workload --file wl-staging.json
```

The command prints the ID of the new workload:

```text
Created Workload with ID <workload-id>
```

`azion describe workload --workload-id <workload-id> --format json` then returns the workload as the API stores it, with its staging workload domain:

```json
{
 "active": true,
 "created_at": "2026-01-01T12:00:00.000000Z",
 "domains": [],
 "id": <workload-id>,
 "infrastructure": 2,
 "last_editor": "<your-email>",
 "last_modified": "2026-01-01T12:00:00.000000Z",
 "mtls": {
  "config": {
   "certificate": null,
   "verification": null
  },
  "enabled": false
 },
 "name": "my-workload",
 "product_version": "1.0",
 "protocols": {
  "http": {
   "http_ports": [
    80,
    8080
   ],
   "https_ports": [
    443,
    8443
   ],
   "versions": [
    "http1",
    "http2"
   ]
  }
 },
 "tls": {
  "certificate": null,
  "ciphers": 4,
  "minimum_version": "tls_1_2"
 },
 "workload_domain": "<id>.preview.azionedge.net",
 "workload_domain_allow_access": true
}
```

Through the API, `POST /v4/workspace/workloads` answers with HTTP `202` and `state` set to `pending`. A production workload created with `name`, `active`, `infrastructure`, and `workload_domain_allow_access` alone returns every default:

```json
{"state":"pending","data":{"id":<workload-id>,"name":"my-workload","active":true,"last_editor":"<your-email>","last_modified":"2026-01-01T12:00:00.000000Z","created_at":"2026-01-01T12:00:00.000000Z","infrastructure":1,"tls":{"certificate":null,"ciphers":7,"minimum_version":"tls_1_3"},"protocols":{"http":{"versions":["http1","http2","http3"],"http_ports":[80],"https_ports":[443],"quic_ports":[443]}},"mtls":{"enabled":false,"config":{"certificate":null,"crl":null,"verification":null}},"domains":[],"workload_domain_allow_access":true,"workload_domain":"<id>.map.azionedge.net","product_version":"1.0"}}
```

The deployment body below binds an application and a firewall through `POST /v4/workspace/workloads/{workload_id}/deployments`:

```json
{"name":"my-deployment","current":true,"active":true,
 "strategy":{"type":"default","attributes":{"application":<application-id>,"firewall":<firewall-id>}}}
```

The API answers with HTTP `202`, `state` set to `pending`, and the deployment with `custom_page` set to `null`:

```json
{"state":"pending","data":{"id":<deployment-id>,"name":"my-deployment","current":true,
 "active":true,"strategy":{"type":"default","attributes":{"application":<application-id>,
 "firewall":<firewall-id>,"custom_page":null}},"last_editor":"<your-email>",
 "last_modified":"2026-01-01T12:00:00.000000Z","created_at":"2026-01-01T12:00:00.000000Z"}}
```

The CLI creates the same binding from flags, here with an application and a custom page set:

```bash
azion create workload-deployment \
  --workload-id <workload-id> \
  --name my-deployment \
  --application-id <application-id> \
  --custom-page <custom-page-id> \
  --strategy-type default \
  --active true \
  --current true
```

The command prints the ID of the new deployment:

```text
Created Workload Deployment with ID <deployment-id>
```

`azion list workload-deployment --workload-id <workload-id> --details` shows the deployment, its application, and its firewall, with `0` for no firewall:

```text
ID      CURRENT  EDGE APPLICATION  EDGE FIREWALL  
<deployment-id>  true     <application-id>        0              
```

---

## Errors

The API refuses each request below with the message in the first column. For a workload or deployment refusal, the CLI prints the message inside `Error: Failed to create the Workload: [...]`, `Error: Failed to update the Workload: [...]`, or `Error: Failed to create the Workload Deployment: [...]`, followed by `Check your settings and try again. If the error persists, contact Azion support.` The `24003` row is the API's answer to a firewall `DELETE`.

| Message                                                                                                                          | Cause                                                                                                                | What to do                                                                                                                                    |
| -------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| `Ensure this field has no more than 100 characters.`                                                                             | `name` is longer than 100 characters.                                                                                | Shorten the name to 100 characters or fewer.                                                                                                  |
| `The infrastructure cannot be changed after Workload creation.`                                                                  | An update changes `infrastructure`.                                                                                  | Leave `infrastructure` out of the update, or create a new workload on the other infrastructure.                                               |
| `Custom hostname is not available in the environment 'Staging Infrastructure'.`                                                  | `domains` holds a hostname on a workload with `infrastructure` set to `2`.                                           | Send `"domains": []` and reach the workload on its workload domain, or use a production workload.                                             |
| `When the workload hostname access is blocked, the workload requires alternate domains or domains.`                              | `workload_domain_allow_access` is `false` and `domains` is empty.                                                    | Add a hostname to `domains`, or set `workload_domain_allow_access` to `true`.                                                                 |
| `This account is not allowed to use the following CNAMEs: example.com.`                                                          | `domains` holds a domain the account has no permission for; the message names it.                                    | Remove the domain, or use a domain the account has permission for.                                                                            |
| `Duplicated usage of suffix in alternate_domains: 'azion.app'.`                                                                  | `domains` holds two `azion.app` hostnames, the same name twice or two different names.                               | Keep one `azion.app` hostname.                                                                                                                |
| `The custom hostname is not available.`                                                                                          | Another workload already holds the `azion.app` hostname.                                                             | Choose another name, or remove it from the other workload first.                                                                              |
| `The domain does not conform to the format defined in RFC 1035.`                                                                 | A `domains` entry is a wildcard, such as `*.azion.app`, or another malformed name.                                   | List each hostname in full.                                                                                                                   |
| `Invalid choices for multiple choices field: [80, 8008, 8080, 8880].`                                                            | `http_ports` holds a port outside the four allowed values.                                                           | Use only `80`, `8008`, `8080`, or `8880`.                                                                                                     |
| `Missing required choices for multiple choices field: ['http1', 'http2'].`                                                       | `versions` holds `http3` without both `http1` and `http2`.                                                           | Send `["http1", "http2", "http3"]`, or remove `http3`.                                                                                        |
| `"9" is not a valid choice.`                                                                                                     | `tls.ciphers` is outside `1` to `8`; the message quotes the value sent.                                              | Send a suite number from `1` to `8`.                                                                                                          |
| `Invalid certificate type, MUST be an Edge Certificate.`                                                                         | `tls.certificate` holds the ID of a Trusted CA certificate.                                                          | Send the ID of a certificate of type `edge_certificate`, or `null`.                                                                           |
| `Invalid certificate type, MUST be a Trusted CA.`                                                                                | `mtls.config.certificate` holds the ID of a server certificate.                                                      | Send the ID of a certificate of type `trusted_ca_certificate`.                                                                                |
| `The maximum number of deployments allowed per workload is 1.`                                                                   | A second deployment is created on a workload that already has one.                                                   | Change the existing deployment with `PATCH /v4/workspace/workloads/{workload_id}/deployments/{deployment_id}`, or in **Deployment Settings**. |
| `24003` `Cannot Delete Firewall`: `To delete this firewall, you must first remove its usage in the following workloads: [<id>].` | A `DELETE` targets a firewall that a workload's deployment still names. Deleting the deployment does not release it. | Delete the workloads the message lists, then repeat the `DELETE`.                                                                             |

---

## Related resources

- [mTLS](/en/documentation/platform/workloads/mtls.md): How a workload verifies client certificates in enforce and permissive mode, with the Trusted CA and CRLs it uses.
- [Workloads limits](/en/documentation/platform/workloads/limits.md): Every bound on a workload, its domains, and its deployment, with what happens past each one.
- [How Workloads works](/en/documentation/platform/workloads/how-it-works.md): The path a request follows from a domain through the workload to its application and firewall.
- [Certificates](/en/documentation/platform/workloads/certificate-manager/certificates.md): The server and Trusted CA certificates a workload accepts, and how to upload or request one.
