Suspend service
POSThttps://api.instacloud.com/projects/{projectId}/services/{serviceId}/suspend
Token scope: account · org · project — read-only tokens refused (not a GET).
Suspend a compute service: takes it offline now, but on the microvm plane it still WAKES ON REQUEST (use stop to keep it offline). On the legacy plane it stays down until start. All plans.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
projectId | path | string | yes | |
serviceId | path | string | yes |
Responses
200
Default Response
| Field | Type | Required | Description |
|---|---|---|---|
service | object | no | A project-level service (postgres | storage | compute | redis | mysql | mongodb). |
service.id | string | no | |
service.project_id | string | no | |
service.type | "postgres" | "storage" | "compute" | "redis" | "mysql" | "mongodb" | no | |
service.name | string | no | |
service.spec | object | no | compute: {cpu_kind,cpus,memory_mb}; postgres: sized by its instance ceiling (cpuMilli/memoryMib) |
service.machine_count | integer | no | compute only |
service.desired_state | "running" | "stopped" | "suspended" | no | compute only — developer-set lifecycle intent |
service.always_on | boolean | no | compute and managed databases (redis, mysql, mongodb) — true: machines never scale to zero; false: idle machines suspend and wake on request. A new compute service is born false (scale-to-zero, except a worker); a new managed database is born from INSTA_DB_ALWAYS_ON_DEFAULT (true on InstaCloud). Postgres is not recorded here: its idle mode lives on the database instance (GET /projects/{projectId}/database/instance, scaleToZero). Billing is actual usage either way. |
service.websocket | boolean | null | no | compute only — the app speaks WebSocket, so its machines carry connections-based concurrency and a 512 MB guest floor. Re-asserted by any redeploy given no flag, including restart. null: never recorded. |
service.endpoint | "http" | "tcp" | "udp" | "tcp+udp" | null | no | compute only — how the service is reached. http: Host-routed HTTPS at `domain`. tcp / udp / tcp+udp: raw TCP, UDP, or both at `endpoint_host`:`port` on the service’s own public IPv6 address (IPv6 clients only; no TLS from the platform, no custom domain, no WebSocket flag). Chosen at create, and changed by a deploy that passes `endpoint`. null: never chosen, which is http. |
service.endpoint_host | string | null | no | compute, endpoint tcp/udp/tcp+udp only — the host to reach on `port` (an IPv6-only name), set once a deploy has confirmed it; null otherwise |
service.region | string | null | no | |
service.domain | string | null | no | default access domain (postgres/compute) |
service.public | boolean | no | storage — bucket(s) served with anonymous public-read; managed databases — the database port is exposed on a public address (on insta-compute, false = reachable only over the private network, *_PRIVATE_URL); postgres — the public endpoint accepts connections (true by default; false = not reachable from the internet, private network lane only); compute — the service answers the internet at its URL / endpoint_host (true by default; false = the URL answers 403 and never wakes it, and only services in the same branch reach it, at private_host). Change it with PUT .../services/{serviceId}/access |
service.private_host | string | null | no | compute and managed databases on insta-compute — the name other services in the SAME project branch reach this one at, on `port` over TCP: `<name>.insta.internal` for compute, `<name>-<type>.insta.internal` for a managed database (redis/mysql/mongodb). Other branches and projects cannot reach it. Resolves through the search domain every service is started with; tools that skip the search list (nslookup, dig) need private_fqdn. null: the service has no private address (a worker, a name ending in '-', a service not yet back-filled, or a region without the private network) |
service.private_fqdn | string | null | no | compute and managed databases on insta-compute — the fully-qualified form of private_host, `<private name>.<network>.insta.internal`, for clients that do not use the search domain. null whenever private_host is |
service.image | string | null | no | compute only — container image currently run |
service.port | integer | null | no | compute/managed database — compute image port, or the private database TCP port |
service.start_command | string | null | no | Runtime startup override, run via sh -c; on insta-compute it runs in place of the image's ENTRYPOINT and CMD: a wrapper entrypoint (e.g. docker-entrypoint.sh) does not run while it is set. null restores the image's own ENTRYPOINT and CMD. Stored as readable service settings. |
service.volume_applied_mount_path | string | null | no | Last successfully confirmed Compute mount path; null means unknown, not proof of a changed path. |
service.volume_mount_path | string | null | no | Compute volume mount path; null or omitted means /data for legacy volumes. Changes apply on deployment. |
service.volume_gib | integer | null | no | compute/managed database — size (whole Gi) of the persistent data volume; null = no volume. Compute can attach/grow via PUT .../volume; managed databases are platform-managed in v1 |
service.pg_version | integer | null | no | postgres only — the Postgres MAJOR version the service runs (e.g. 16), known before the instance is ever connected to or woken. Pick client tooling (pg_dump/pg_restore/psql) of the same major. null: never recorded (a legacy row). The exact server_version of a RUNNING instance is on GET .../database/metrics |
service.template_deployment_id | string | null | no | the template deployment that created this service (survives branch clones); null for services created directly |
service.template_modified | boolean | no | true once the service was reconfigured away from its template-deployed spec |
service.template_code | string | null | no | the template this service was deployed from; null for services created directly, and for one whose deployment record has been pruned |
service.template_logo_url | string | null | no | the template's mark; null when the template is not in the registry (or carries no logo). Official templates: a commit-pinned jsDelivr URL (TEMPLATE_LOGO_HOST). Community templates: any https:// link the author set. Joined live rather than stored, because a republish moves it |
service.template_name | string | null | no | the template's name as the registry spells it, for a surface people read; null when the template is not in the registry, or its manifest omits a name. Read from the manifest the registry serves NOW, beside the logo, because a republish can rename it |
service.template_version | string | null | no | the template version this instance was deployed from; null for a service created directly. Read from the deployment record, so it does not move when the registry is republished |
service.template_latest_version | string | null | no | the version the registry serves for this template now; null when the registry does not serve it — absent, unpublished or taken down. The row still reports template_code and template_name in those cases, because attribution of a resource its owner deployed is not catalog visibility. For display beside template_version, never for deciding whether an update exists |
service.template_update_available | boolean | no | true when upgrading this service's template deployment to the version the registry serves now would actually change something about the services it runs: a setting the new manifest would write, an environment variable it would write differently, a service it would add, or a variable it now requires that this instance holds no value for. A republish that only moved presentation is not an update, because applying it would change nothing, and neither is a new version string on identical content, which is what every community republish produces. False whenever the answer cannot be determined: a template absent from the registry, unpublished, taken down, a manifest this version of the platform cannot parse, or a registry read that failed. False too while the deployment's own run has not succeeded, because what an unfinished deploy needs is a retry, not an upgrade |
service.source | object | no | compute only — where the running image comes from: an image somebody deployed (type=image) or a connected repository (type=github). Full resource: GET /projects/{id}/services/{serviceId}/source |
service.source.type | "image" | "github" | yes | |
service.source.owner | string | no | |
service.source.repo | string | no | |
service.source.branch | string | no | the repo branch this service tracks |
service.source.auto_deploy | boolean | no | a push to `branch` rebuilds and redeploys the service |
service.status | "creating" | "active" | "error" | "deleting" | "deleted" | no | |
service.created_at | string | no | |
state | string | no | live runtime state: running|suspended|stopped|none|unknown |
202
Default Response
| Field | Type | Required | Description |
|---|---|---|---|
status | string | yes | |
approvalId | string | yes | |
action | string | yes | |
actions | string[] | yes | |
message | string | yes | |
url | string | yes |
400
Default Response
| Field | Type | Required | Description |
|---|---|---|---|
error | string | yes |
403
Default Response
| Field | Type | Required | Description |
|---|---|---|---|
error | string | yes |
404
Default Response
| Field | Type | Required | Description |
|---|---|---|---|
error | string | yes |