Skip to content
Console
Menu

Queues

Workflows

Getting Started

Authentication

KV Store

Configuration

The spec of a Service, field by field, and the two ways to change it.

Today this runs on the management API

A service's variables are changed on the management API: GET, POST ({"key","value"}), PATCH and DELETE (?key=) on /v1/projects/{id}/services/{name}/env. Its size and port are PATCH /v1/projects/{id}/services/{name} (for example {"instanceType":"nano"}). The sylphx hosting services update commands below show the resource-model spelling of the same settings. The Hosting quickstart has the full sequence.

Everything a Service is, is its spec. This page is the spec, field by field, with the reason to touch each one.

#Environment variables

Two fields, and the difference between them is where the value lives:

FieldTypeWhat it is
envmap<string, string>Plain environment variables, in the spec and readable by anyone who can read the Service. For a URL, a feature flag, a log level.
secret_envmap<string, string>Variable name to Secret name. The platform resolves the value at instance start; the value never enters the spec.

A secret is created once, and named from as many Services as need it:

Shell
sylphx secrets secrets create --parent orgs/acme/projects/shop/envs/production \
  --meta.display-name SHOP_DATABASE_URL shop-database-url
sylphx secrets secret-versions create \
  --parent orgs/acme/projects/shop/envs/production/secrets/shop-database-url \
  --payload "$DATABASE_URI"
Shell
sylphx hosting services update orgs/acme/projects/shop/envs/production/services/shop \
  --spec.secret-env DATABASE_URL=shop-database-url
Shell
curl -X PATCH "https://api.sylphx.com/v1/orgs/acme/projects/shop/envs/production/services/shop" \
  -H "Authorization: Bearer $SYLPHX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"service": {"name": "orgs/acme/projects/shop/envs/production/services/shop", "spec": {"secret_env": {"DATABASE_URL": "shop-database-url"}}}}'

A secret never goes in env

env is stored in the spec and read back by anyone with hosting:read — it is the wrong place for a password, a token or a connection string with credentials in it. If the value would be embarrassing in a screenshot, it is a Secret.

Rotating a secret is a new version of the Secret; the Services bound to it pick it up on their next instance start. Nothing about it is copied into the spec, so there is nothing to update twice.

#Where the code comes from

FieldTypeWhat it is
source.source_linkstringBuild from this SourceLink’s repository on every push to branch.
source.imagestringRun an Artifact by digest: registry.sylphx.net/<path>@sha256:<hex>. No build, and branch is ignored.
source.branchstringThe branch that ships to this Service. The SourceLink’s production branch by default.
source.build.root_directorystringThe directory inside the repository to build; the root by default.
source.build.dockerfilestringA Dockerfile path relative to root_directory. Unset lets the zero-config frontend detect the stack.
source.build.build_classstringThe Build class, sylphx-<os>-<size>; sylphx-linux-standard by default.
commandstringOverrides the image’s command — a worker runs its process here rather than on a port.

Everything about the build that is not in the spec is in the repository. A Service does not carry its own manifest: what it runs is what the source says, and re-declaring the build in two places is how they drift apart.

#How it is exposed

FieldTypeWhat it is
portint32The port the application listens on. The public edge stays 443.
exposureServiceExposurepublic (default) puts the Service behind the edge; internal keeps it reachable only from inside the environment.
regionsstring[]Regions to run in; the project’s home region by default.

An internal Service is how a backend is reached: it has no public host, and a Route cannot point at it from the edge. Data stays near its users by putting the Service where they are — the Region you choose for a database and the regions you choose for the Service that reads it are the same decision made twice, so make them match.

#Size and scaling

FieldTypeWhat it is
sizeInstanceSizenano, micro, small, standard, large, xlarge or xxlarge. The plan’s default when unset.
scaling.min_instancesint32Instances kept running with no traffic. 0 idles to zero and wakes on request.
scaling.max_instancesint32Instances at most. 0 means the plan’s limit.
Shell
sylphx hosting services update orgs/acme/projects/shop/envs/production/services/shop \
  --spec.size small \
  --spec.scaling.min-instances 0 \
  --spec.scaling.max-instances 10

Start at zero and raise min_instances only if the cold start is worth paying for: an instance kept idle serves the first request faster and costs the same as a busy one.

#Probing

FieldTypeWhat it is
health.protocolHealthProtocolhttp or tcp. Required.
health.pathstringThe HTTP path to probe when the protocol is HTTP.
health.startup_timeoutdurationHow long a new instance may take to pass its first probe.

A tcp probe only asks whether something is listening, which is right for a worker that has no HTTP surface. An http probe is the one that can tell a finished boot from a listening socket. Health checks has the rest.

#Changing a Service

Every field above changes through update, and a change to the spec is a new generation: the platform builds it, and it ships the way anything else does — by rolling out. Writing the spec is not the deploy; the rollout is.