Skip to main content

Services

The services object is the core of a FlowLayer config.

Each entry defines one runtime service keyed by its service name.

Shape

{
"services": {
"db": {
"cmd": ["postgres", "-D", "./var/db"],
"port": 5432,
"ready": {
"type": "tcp"
}
},
"api": {
"cmd": ["go", "run", "./cmd/api"],
"dependsOn": ["db"],
"env": {
"PORT": "3000"
},
"port": 3000,
"logView": {
"maxEntries": 300
}
}
}
}

services.<name>

The object key is the service identifier. FlowLayer uses it in multiple places:

  • dependsOn references
  • runtime commands such as start_service and stop_service
  • log entries and projected filenames such as api.jsonl

The runtime does not normalize service names. Use one stable spelling everywhere.

dependsOn

Use dependsOn to declare service-to-service dependencies:

{
"services": {
"db": {
"cmd": ["postgres", "-D", "./var/db"]
},
"api": {
"cmd": ["go", "run", "./cmd/api"],
"dependsOn": ["db"]
}
}
}

Confirmed behavior:

  • every dependency must reference another service in the same config
  • empty dependency entries are rejected
  • a service cannot depend on itself
  • duplicate dependencies are removed during validation
  • dependency order in the file does not control startup order

FlowLayer computes startup waves from the dependency graph. See Waves.

env

env is a map of environment variables for the service process:

{
"services": {
"api": {
"cmd": ["go", "run", "./cmd/api"],
"env": {
"PORT": "3000",
"APP_ENV": "dev"
}
}
}
}

FlowLayer starts from its own process environment, then applies services.<name>.env on top. A service value overrides an inherited value with the same key.

The same merged environment is used for cmd and stopCmd.

port

port is an optional integer hint with runtime consequences:

  • it must be >= 0
  • if port > 0, FlowLayer checks that the port is free before start
  • if port > 0, FlowLayer verifies that the port is released before declaring stop complete
  • if ready.type is tcp and ready.port is omitted, FlowLayer uses service.port

A missing or zero port means FlowLayer does not do port-based start/stop checks for that service.

logView

services.<name>.logView.maxEntries sets the default log limit for service-scoped get_logs requests:

{
"services": {
"api": {
"cmd": ["go", "run", "./cmd/api"],
"logView": {
"maxEntries": 300
}
}
}
}

When provided, maxEntries must be greater than 0.

For limit resolution rules, see Logs.

Other service fields

Other confirmed service fields are documented on dedicated pages:

  • cmd and stopCmd: Commands
  • ready: Readiness
  • kind: daemon by default, or oneshot for services that are expected to exit after successful start

Naming guidance

Good service names are operational identifiers, not display labels.

Prefer names that are:

  • short and stable
  • descriptive in logs and commands
  • safe to reuse in filenames and scripts

Typical names are api, db, users, or billing-worker.

Avoid spaces, punctuation-heavy names, or casual renames. In FlowLayer, the name is what other services depend on and what operators type into runtime commands.

For process fields, continue with Commands. For readiness gates, continue with Readiness.