Skip to main content
Every entry under services: in your spec has a type. The type decides whether the service runs continuously, whether it can receive traffic, and which fields apply to it. If you omit type:, the service is a web service.

Which type do I need?

A web service is reachable from the internet only if one of its ports is marked public: true. Leave every port private and it is reachable by its siblings inside the project and by nothing else. The console’s New menu offers the same taxonomy as three entries: a Web Service (a port, exposed at a public URL), a Private Service (a port, reachable only by siblings), and a Background Worker (no incoming port at all). All three are spellings of the table below — a private service is a web service whose port is not public.

The four types

web

A resident container that can receive HTTP. Mark at most one port public: true to give it a URL at <prefix>.<apps-base-domain>. Leave every port private and the service is reachable only by its siblings inside the project. A web service is the only type that can use healthCheckPath, and the only type that can sleep on idle, because HTTP traffic is the wake signal — and sleeping additionally requires the public port, since the wake signal arrives at the edge.

Changing exposure later

Exposure is not fixed at creation. On the service’s Settings tab, the Public exposure section edits the port and an Expose to the internet switch; applying redeploys the service. Exposing mints the service’s URL; unexposing withdraws it (the route is removed at the next deploy) while siblings keep reaching the service privately. Re-exposing later brings the same hostname back. Two caveats. The controls edit the service’s stored spec, so a service that deploys from a committed slipway.yaml shows its ports read-only — edit the file instead. And features that require a public URL (auth, ipRules, edgeCache, prefix, domain) must be removed before unexposing; the platform strips prefix/domain for you and refuses the change while the others are present.

Changing the build later

The same tab has a Build section for every service built from a repository, whatever its type: the root directory, whether it builds with the committed Dockerfile or a language runtime and which version, the build command, the start command (the command, for a cron job), and for a static site the publish directory. Applying rebuilds and redeploys the service. The same read-only rule applies to a committed slipway.yaml.

worker

A resident container with no ports. It has no ingress and no URL, and nothing outside the project can reach it. Use it for work that is driven by a queue or a timer inside the process rather than by an inbound request. Because a worker cannot receive HTTP, it cannot be woken by traffic. Workers run continuously rather than sleeping on idle.

cron

Not resident. slipway runs the container on the schedule you give it and the container exits. schedule: is required and is a five-field UTC cron expression. If a run is still going when the next one is due, the next run is skipped rather than queued. A cron service cannot declare ports, replicas above one, a health check, a disk, or dependsOn.

static

Not a container. The build runs, the directory named by publish: is uploaded, and the CDN serves it. There is no pod, so a static service has no CPU or memory setting, no shell, no scaling, no disk and no sleep policy. Static services are not billed for compute. See Static sites.

What each type supports

Setting a field on a type that does not support it fails validation with the reason, rather than being ignored.

Databases are services too

A managed database is an ordinary service with a pinned engine image, a generated password, and a disk at the engine’s data path. Declare one with the databases: block or create it under New → Database. It behaves like a web service with no public port: siblings reach it at postgres:5432, and nothing outside the project can.

Appendix: glossary