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

# Service types

> Pick the right service type for each part of your app.

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?

```mermaid theme={"system"}
flowchart LR
  start{{"What does<br/>the service do?"}}

  static["<b>static</b><br/>built once, served from the CDN"]
  web["<b>web</b><br/>resident, answers HTTP"]
  cron["<b>cron</b><br/>runs on a schedule"]
  worker["<b>worker</b><br/>resident, no ports"]

  start e1@-->|"serves prebuilt files"| static
  start e2@-->|"answers HTTP"| web
  start e3@-->|"runs on a schedule"| cron
  start e4@-->|"runs continuously"| worker

  e1@{animation: slow}
  e2@{animation: slow}
  e3@{animation: slow}
  e4@{animation: slow}

  classDef choice fill:#0D857714,stroke:#0D8577,stroke-width:1.5px
  classDef result fill:#2DD4BF22,stroke:#0D8577,stroke-width:2px
  class start choice
  class static,web,cron,worker result
```

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

| Type | Runs | Public URL | Typical use |
| - | - | - | - |
| `web` | Continuously | Only with a port marked `public: true` | APIs, server-rendered apps, internal services |
| `worker` | Continuously | Never | Queue consumers, background processors |
| `cron` | On a schedule | Never | Nightly jobs, cleanup, report generation |
| `static` | Built once, served from the CDN | Always | SPAs, marketing sites, docs |

### 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](/services/static).

## What each type supports

| Field | `web` | `worker` | `cron` | `static` |
| - | - | - | - | - |
| `ports` | Yes | No | No | No |
| `prefix`, `domain` | With a public port | No | No | Yes |
| `healthCheckPath` | Yes | No | No | No |
| `healthcheck` | Yes | Yes | No | No |
| `cpu`, `memory` | Yes | Yes | Yes | No |
| `replicas`, `scaling` | Yes | Yes | No | No |
| `disk` | Yes | Yes | No | No |
| `dependsOn` | Yes | Yes | No | No |
| `preDeploy` | Yes | Yes | Yes | No |
| `schedule` | No | No | Required | No |
| `publish` | No | No | No | Required |
| `command`, `args`, `workDir`, `files` | Yes | Yes | Yes | No |

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:`](/slipway-yaml/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

| Term | Meaning |
| - | - |
| Resident | The container runs continuously, rather than per request or per schedule. |
| Public port | A port marked `public: true`, which gives the service a hostname at the edge. At most one per service. |
| Wakeable | A service that can be brought back from sleep, which requires it to receive HTTP. Only `web` services with a public port qualify. |
| Sibling | Another service in the same project, reachable by bare name on the private network. |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.