WakaStart
Sources & services

Service — executable component

ServiceDefinition (architecture) vs ServiceInstance (environment): the 2-level pattern.

Version v1.04 min read

Service — executable component

📍 Where to find this in the UI

  • ServiceDefinitions: Infra → Architecture tab → Services
  • ServiceInstances: Infra → Environments → {env} → Services

What is it? A service is a piece of code that runs continuously (backend, frontend, worker, API…).

In Wakastart, a service is defined at 2 levels.

ServiceDefinition (Architecture level)

This is the generic definition of the service. You describe:

FieldExampleExplanation
RoleBACKBackend, frontend, API, worker…
ProtocolHTTP / GRPC / TCPHow the service is addressed
Port3000The service's listening port
Repositorythe WakaStart BFFThe Git repo the code comes from (see Repository)
rootDirectory / dockerfilePath / buildContext(see dedicated section below)How Wakastart finds and builds the Dockerfile
CPU / Memory requests/limits100m CPU, 128Mi RAMAllocated resources
Replicas1, 2, …How many instances run in parallel
Required variablesJWT_SECRET, MONGO_URLList of variables the service needs (see Variables and secrets)

→ The ServiceDefinition is the schema, not the thing that actually runs.

Configuring the build: rootDirectory, dockerfilePath, buildContext

Three ServiceDefinition parameters drive the docker build step:

FieldRoleRelative to
rootDirectoryBase directory used as a "virtual root" for this service within the repo. All paths below are relative to it.The repo root
dockerfilePathPath to the Dockerfile used to build the image.rootDirectory
buildContextThe context sent to docker build (the set of files accessible via COPY / ADD in the Dockerfile).rootDirectory

The docker build that gets executed is equivalent to:

bash
cd <repo>/<rootDirectory> docker build -f <dockerfilePath> <buildContext>

Case 1 — Simple repo, Dockerfile at the root

text
le BFF WakaStart/ ├── Dockerfile ├── package.json └── src/
FieldValue
rootDirectory./
dockerfilePathDockerfile
buildContext.

Equivalent to: docker build -f Dockerfile . run at the repo root.

Case 2 — Monorepo, project in a subfolder

text
le BFF WakaStart/ ├── apps/ │ ├── backend/ │ │ ├── Dockerfile │ │ ├── package.json │ │ └── src/ │ └── worker/ └── packages/

You want to build only apps/backend and restrict Docker's access to files in that folder:

FieldValue
rootDirectoryapps/backend/
dockerfilePathDockerfile
buildContext.

Equivalent to: cd apps/backend && docker build -f Dockerfile ..

The build only sees apps/backend/ — neither apps/worker/ nor packages/.

Case 3 — Monorepo with a shared lockfile (pnpm/yarn workspaces, turbo…)

Your service is in apps/backend/ but needs the root pnpm-lock.yaml and the shared packages/* packages to install:

text
le BFF WakaStart/ ├── pnpm-lock.yaml ← lockfile racine ├── pnpm-workspace.yaml ├── apps/ │ └── backend/ │ └── Dockerfile ← Dockerfile dédié, mais a besoin du contexte racine └── packages/ └── shared/
FieldValue
rootDirectory./
dockerfilePathapps/backend/Dockerfile
buildContext.

Equivalent to: docker build -f apps/backend/Dockerfile . at the repo root.

The Dockerfile can now do COPY pnpm-lock.yaml ./ and COPY packages/shared ./packages/shared since it has access to the whole repo.

Practical rules

  • The smaller the buildContext, the faster the build (Docker sends fewer files to the daemon). If your service is self-contained in a subfolder, go with Case 2.
  • If your Dockerfile needs files located above its own folder (root lockfile, sibling packages), go with Case 3 — a larger buildContext but a targeted dockerfilePath.
  • A .dockerignore at the root of the buildContext excludes unwanted files (node_modules, .git, .next/cache…) from the context sent to the daemon.

ServiceInstance (Environment level)

This is the actual instance of a service in a given environment (e.g. backend in dev, backend in prod). It inherits default values from the Definition but can override them:

text
ServiceDefinition "backend" ServiceInstance backend (env prod) ├── role: BACK ├── definitionId → lien ├── defaultReplicas: 1 ├── replicas: 5 ← override prod ├── defaultPort: 3000 ├── port: null ← utilise 3000 └── defaultMemoryLimit: 512Mi └── memoryLimit: 2Gi ← override prod

This is where the ServiceInstance:

  • decides which Docker image is deployed (and therefore which build is used)
  • binds variables to their actual values
  • shows the deployments, logs, and metrics