> ## Documentation Index
> Fetch the complete documentation index at: https://docs.simplismart.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Deployments

> Manage deployments using the Simplismart Python SDK

Manage deployments using the `Simplismart` client methods below (e.g. `client.create_deployment(...)`).

### `create_deployment`

Creates a deployment for a model repo.

<Note>
  Use env for model repo UUID and organization ID (e.g. `ORG_ID`); do not hardcode secrets.
</Note>

The example below deploys a model on an H100 with 1 to 2 replicas that autoscale on GPU utilization (target 80%), with fast scale-up enabled.

```python theme={null}
import os
from dotenv import load_dotenv
load_dotenv()

from simplismart import DeploymentCreate, Simplismart

client = Simplismart()
deployment = client.create_deployment(
    DeploymentCreate(
        model_repo=os.getenv("MODEL_REPO_ID", "model-repo-uuid"),
        org=os.getenv("ORG_ID"),
        gpu_id="nvidia-h100",
        name="vision-private-deploy",
        min_pod_replicas=1,
        max_pod_replicas=2,
        autoscale_config={"targets": [{"metric": "gpu", "target": 80}]},
        env_variables={"KEY": "value"},
        healthcheck={"path": "/", "port": 8000},
        ports={"http": {"port": 8000}},
        metrics_path=["/v1/chat/completions"],
        fast_scaleup=True,
        deployment_tag="v1.0",
        auth_enabled=False,
        extra_details={"is_websocket_enabled": False},
    )
)
```

#### DeploymentCreate

| Parameter                         | Type                   | Description                                                                                          | Required    |
| --------------------------------- | ---------------------- | ---------------------------------------------------------------------------------------------------- | ----------- |
| `model_repo`                      | `str`                  | Model repository UUID                                                                                | Yes         |
| `org`                             | `str`                  | Organization UUID (`org_id`)                                                                         | Yes         |
| `gpu_id`                          | `str`                  | GPU type identifier. Examples: `nvidia-h100`, `nvidia-a10`, `nvidia-l4`                              | Yes         |
| `name`                            | `str`                  | Deployment name (3-255 chars)                                                                        | Yes         |
| `min_pod_replicas`                | `int`                  | Minimum pod replicas (≥ 0). When using `cronScaling`, set to `0` to scale to zero outside the window | Yes         |
| `max_pod_replicas`                | `int`                  | Maximum pod replicas (≥ 1)                                                                           | Yes         |
| `autoscale_config`                | `AutoscaleConfig`      | Autoscaling configuration. Required unless `min_pod_replicas` and `max_pod_replicas` are both `1`    | Conditional |
| `env_variables`                   | `dict \| None`         | Environment variables                                                                                | No          |
| `deployment_custom_configuration` | `dict \| None`         | Custom deployment config                                                                             | No          |
| `healthcheck`                     | `dict \| None`         | Health check configuration                                                                           | No          |
| `ports`                           | `dict \| None`         | Port mappings                                                                                        | No          |
| `metrics_path`                    | `list \| None`         | Metrics paths                                                                                        | No          |
| `persistent_volume_claims`        | `dict \| list \| None` | PVC configurations                                                                                   | No          |
| `fast_scaleup`                    | `bool \| None`         | Enable fast scale up                                                                                 | No          |
| `deployment_tag`                  | `str \| None`          | Deployment tag label                                                                                 | No          |
| `scale_to_zero_enabled`           | `bool`                 | Traffic-based scale-to-zero (scales down on idle traffic). Default `false`                           | No          |
| `async_deployment_type`           | `str \| None`          | One of `SYNC`, `ASYNC`                                                                               | No          |
| `auth_enabled`                    | `bool \| None`         | Enable authentication on the deployment endpoint                                                     | No          |
| `extra_details`                   | `dict \| None`         | Extra container details, e.g. `{"is_websocket_enabled": False}`                                      | No          |
| `deployment_input_files`          | `list \| None`         | Input file mounts, e.g. `[{"name": "weights", "path": "/mnt/weights"}]`                              | No          |

<Info>
  A deployment scales using **one** of two approaches, and they cannot be combined:

  * **Traffic-based** (`scale_to_zero_enabled=True`): scales down when the deployment is idle.
  * **Cron-based / schedule-based** (`cronScaling`): runs on a fixed schedule. Set `min_pod_replicas=0` if you also want it to scale to zero outside the scheduled window.
</Info>

#### AutoscaleConfig

```python theme={null}
autoscale_config = {
    "targets": [
        {
            "metric": "gpu",      # Required
            "target": 80,          # Required (number)
            "percentile": 95      # Optional, only for latency metric
        }
    ]
}
```

| Metric Option | Description                                           |
| ------------- | ----------------------------------------------------- |
| `concurrency` | Number of concurrent requests                         |
| `cpu`         | CPU utilization percentage                            |
| `gpu`         | GPU utilization percentage                            |
| `gram`        | GPU memory utilization                                |
| `latency`     | Request latency (supports percentiles 50, 75, 90, 95) |
| `ram`         | RAM utilization                                       |
| `throughput`  | Requests per second                                   |

<Note>
  The `percentile` field is only supported when `metric` is set to `latency`.
</Note>

These are the same scaling metrics you set when [creating a deployment](/model-suite/deployments/creating-a-deployment) in the Model Suite. For what each metric measures and how thresholds trigger scaling, see [Add Scaling Metrics](/model-suite/deployments/creating-a-deployment#add-scaling-metrics).

#### Cron-based Scaling

Cron-based scaling (called schedule-based scaling on the Simplismart platform) runs your deployment on a fixed schedule. Use it when traffic is predictable: for example, keep the deployment up during weekday business hours and shut it down outside that window. Add a `cronScaling` config to `autoscale_config`, and set `min_pod_replicas=0` if you want it to scale to zero outside the scheduled window.

```python theme={null}
deployment = client.create_deployment(
    DeploymentCreate(
        model_repo=os.getenv("MODEL_REPO_ID", "model-repo-uuid"),
        org=os.getenv("ORG_ID"),
        gpu_id="nvidia-h100",
        name="my-deployment-cron",
        min_pod_replicas=0,
        max_pod_replicas=2,
        autoscale_config={
            "targets": [{"metric": "gpu", "target": 80}],
            "cronScaling": [
                {"timezone": "UTC", "start": "0 9 * * 1,2,3,4,5", "end": "0 18 * * 1,2,3,4,5", "desiredReplicas": 2}
            ],
        },
    )
)
```

The schedule above runs 2 pods (`desiredReplicas`) on weekdays 9am to 6pm UTC, and because `min_pod_replicas=0` it scales to zero outside that window.

##### CronScalingRule fields

Each entry in `cronScaling` is validated against this shape. Unknown keys are rejected.

| Field             | Type  | Required | Description                                                  |
| ----------------- | ----- | -------- | ------------------------------------------------------------ |
| `timezone`        | `str` | Yes      | IANA timezone, e.g. `UTC`                                    |
| `start`           | `str` | Yes      | Cron expression for when the active window starts            |
| `end`             | `str` | Yes      | Cron expression for when the active window ends              |
| `desiredReplicas` | `int` | No       | Replicas to run inside the window (default `1`, minimum `1`) |

### `list_deployments`

Lists deployments with optional filtering.

```python theme={null}
import os
from dotenv import load_dotenv
load_dotenv()

from simplismart import Simplismart

client = Simplismart()
deployments = client.list_deployments(
    model_repo_id=os.getenv("MODEL_REPO_ID"),  # Optional
    status="DEPLOYED",
    offset=0,
    count=20,
)
print(deployments)
```

**Expected output** — list of deployment summary objects:

```json theme={null}
[
  {
    "deployment_id": "deployment-uuid",
    "deployment_name": "speechbrain-v3",
    "model_repo_id": "model-repo-uuid",
    "model_repo_name": "speechbrain",
    "model_type": "unknown",
    "accelerator_type": ["nvidia-l40s"],
    "accelerator_count": 1,
    "status": "DEPLOYED"
  }
]
```

#### Deployment Status Options

| Value      | Description                 |
| ---------- | --------------------------- |
| `DEPLOYED` | Deployment is running       |
| `PENDING`  | Deployment is being created |
| `FAILED`   | Deployment failed           |
| `STOPPED`  | Deployment is stopped       |
| `DELETED`  | Deployment has been deleted |

### `list_model_deployments`

Lists all model deployments for an organization.

```python theme={null}
deployments = client.list_model_deployments(org_id="org-uuid")
```

### `get_model_deployment`

Gets deployment details by ID. Set `DEPLOYMENT_ID` in env or use an id from `list_deployments`.

```python theme={null}
deployment = client.get_model_deployment(deployment_id=os.getenv("DEPLOYMENT_ID", "deployment-uuid"))

print(deployment)
```

**Expected output** — deployment object with `uuid`, `name`, `status`, `model_repo`, `org`, `autoscale_config`, `healthcheck`, `ports`, `min_pod_replicas`, `max_pod_replicas`, etc.

### `get_deployment`

Get deployment details by ID.

```python theme={null}
deployment = client.get_deployment(deployment_id=os.getenv("DEPLOYMENT_ID", "deployment-uuid"))
```

### `update_deployment`

Updates deployment configuration.

```python theme={null}
updated = client.update_deployment(
    deployment_id=os.getenv("DEPLOYMENT_ID", "deployment-uuid"),
    payload={
        "min_pod_replicas": 1,
        "max_pod_replicas": 2,
        "autoscale_config": {"targets": [{"metric": "gpu", "target": 80}]},
    },
)
```

### `stop_deployment`

Stops a running deployment.

```python theme={null}
result = client.stop_deployment(deployment_id=os.getenv("DEPLOYMENT_ID", "deployment-uuid"))
```

### `start_deployment`

Starts a stopped deployment.

```python theme={null}
result = client.start_deployment(deployment_id=os.getenv("DEPLOYMENT_ID", "deployment-uuid"))
```

### `restart_deployment`

Restarts a deployment.

```python theme={null}
result = client.restart_deployment(
    deployment_id=os.getenv("DEPLOYMENT_ID", "deployment-uuid"),
)
```

### `fetch_deployment_health`

Gets deployment health status.

```python theme={null}
health = client.fetch_deployment_health(deployment_id=os.getenv("DEPLOYMENT_ID", "deployment-uuid"))

print(health)
```

**Expected output**

```json theme={null}
{
  "data": "Healthy",
  "messages": [
    {
      "message": "Ready to use, the model is running and available for inference.",
      "severity": "info"
    }
  ],
  "pods": { "ready": 1, "not_ready": 0 }
}
```

### `update_deployment_autoscaling`

Updates the autoscaling configuration of a live deployment.

<Note>
  `cronScaling`, `targets`, `scaleDownBehavior`, and `scaleUpBehavior` are **top-level** fields here — unlike `create_private_deployment` / `update_deployment`, where they nest inside `autoscale_config`. Two rules are enforced client-side **before** the request, so you get a clear `ValueError` instead of a backend `400`:

  * `min_replicas=0` is only allowed together with `cron_scaling`.
  * `scale_to_zero` and `cron_scaling` cannot both be set.
</Note>

| Parameter                 | Type                    | Description                                                     | Required |
| ------------------------- | ----------------------- | --------------------------------------------------------------- | -------- |
| `deployment_id`           | `str`                   | Deployment UUID                                                 | Yes      |
| `min_replicas`            | `int`                   | Minimum replicas (≥ 0). `0` requires `cron_scaling`             | Yes      |
| `max_replicas`            | `int`                   | Maximum replicas (≥ 1, ≥ `min_replicas`)                        | Yes      |
| `scale_to_zero`           | `bool`                  | Traffic-based scale-to-zero. Cannot combine with `cron_scaling` | No       |
| `cron_scaling`            | `list[CronScalingRule]` | Schedule-based scaling windows                                  | No       |
| `cooldown_period`         | `int`                   | KEDA cooldown (seconds)                                         | No       |
| `initial_cooldown_period` | `int`                   | KEDA initial cooldown (seconds)                                 | No       |
| `targets`                 | `list[AutoscaleTarget]` | KEDA metric targets (`metric`, `target`, optional `percentile`) | No       |
| `scale_up_behavior`       | `HPAScalingBehavior`    | HPA scale-up behavior                                           | No       |
| `scale_down_behavior`     | `HPAScalingBehavior`    | HPA scale-down behavior                                         | No       |

```python theme={null}
# Plain min/max replicas
client.update_deployment_autoscaling(
    deployment_id=os.getenv("DEPLOYMENT_ID", "deployment-uuid"),
    min_replicas=1,
    max_replicas=3,
)

# Traffic-based scale-to-zero with a cooldown
client.update_deployment_autoscaling(
    deployment_id="<DEPLOYMENT_ID>",
    min_replicas=1, max_replicas=3,
    scale_to_zero=True, cooldown_period=30,
)
```

```python theme={null}
from simplismart import (
    AutoscaleTarget,
    CronScalingRule,
    HPAScalingBehavior,
    Simplismart,
)

client = Simplismart()

# Cron window — min_replicas=0, run only weekdays 8am–6pm UTC
client.update_deployment_autoscaling(
    deployment_id="<DEPLOYMENT_ID>",
    min_replicas=0, max_replicas=2,
    cron_scaling=[
        CronScalingRule(timezone="UTC", start="0 8 * * 1-5", end="0 18 * * 1-5", desiredReplicas=1)
    ],
)

# Metric targets + both HPA behaviors
# Scale on p95 latency; ramp up fast (4 pods / 15s), scale down gently (25% / 60s).
client.update_deployment_autoscaling(
    deployment_id="<DEPLOYMENT_ID>",
    min_replicas=1, max_replicas=8,
    targets=[AutoscaleTarget(metric="latency", target=200, percentile=95)],
    scale_up_behavior=HPAScalingBehavior(
        stabilizationWindowSeconds=0,
        selectPolicy="Max",
        policies=[{"type": "Pods", "value": 4, "periodSeconds": 15}],
    ),
    scale_down_behavior=HPAScalingBehavior(
        stabilizationWindowSeconds=300,
        selectPolicy="Min",
        policies=[{"type": "Percent", "value": 25, "periodSeconds": 60}],
    ),
)
```

<Note>
  `AutoscaleTarget` and `HPAScalingBehavior` / `HPAScalingPolicy` validate locally before the request: `percentile` is only valid for the `latency` metric and must be one of `50, 75, 90, 95`; HPA policy `type` is `Pods` or `Percent`, `value` must be a positive integer (`≤ 100` for `Percent`), `periodSeconds` ∈ `[1, 1800]`, and `stabilizationWindowSeconds` ∈ `[0, 3600]`.
</Note>

### `delete_deployment`

Deletes a deployment.

```python theme={null}
result = client.delete_deployment(
    deployment_id=os.getenv("DEPLOYMENT_ID", "deployment-uuid"),
)
```

***

## Error Handling

The SDK raises `SimplismartError` for all API errors.

```python theme={null}
from simplismart import Simplismart, SimplismartError

client = Simplismart()
try:
    deployment = client.get_deployment(deployment_id="00000000-0000-0000-0000-000000000000")
except SimplismartError as e:
    print("Status:", e.status_code)
    print("Message:", e)
    print("Payload:", e.payload)
```

**Expected output** (for invalid or missing deployment):

```
Caught SimplismartError:
  status_code: 404
  message: No ModelDeployment matches the given query. (status=404)
  payload: {'detail': 'No ModelDeployment matches the given query.'}
```

#### SimplismartError Attributes

| Attribute     | Type   | Description                 |
| ------------- | ------ | --------------------------- |
| `status_code` | `int`  | HTTP status code            |
| `payload`     | `dict` | Full error response payload |
| `message`     | `str`  | Error message from backend  |

***

## BYOC Deployment

Create a BYOC deployment with a payload (cluster, nodegroup, etc.). See [Bring your own compute](/inference/bring-your-own-compute) and [Deploy on imported cluster](/model-suite/deployments/deploy-on-an-imported-cluster).

`create_byoc_deployment` takes a **raw dict** (no typed model). BYOC scheduling fields such as `nodegroups` and `cluster` are intentionally not part of `DeploymentCreate`.

```python theme={null}
from simplismart import Simplismart

client = Simplismart()

resp = client.create_byoc_deployment({
    "model_repo": "<MODEL_REPO_ID>",
    "org": "<YOUR_ORG_UUID>",
    "name": "my-byoc-deploy",
    "min_pod_replicas": 1,
    "max_pod_replicas": 1,
    "nodegroups": ["<NODEGROUP_ID>"],
})

print(resp)
```
