Examples

Real-world configuration patterns for common project setups.

E-commerce Platform

A Go microservices platform with 5 tiers, readiness checks, hot-reload, and multiple profiles. Uses YAML anchors to keep the config DRY.

YAML Anchors

Define reusable readiness, logging, and watch blocks at the top of your config. Services reference them with *anchor or merge with <<: *anchor to override specific fields.

fuku.yaml
version: 1

# ── Reusable anchors ──

x-readiness-http: &readiness-http
  type: http
  timeout: "30s"
  interval: "500ms"

x-readiness-tcp: &readiness-tcp
  type: tcp
  timeout: "30s"
  interval: "500ms"

x-readiness-log: &readiness-log
  type: log
  pattern: "Server started"
  timeout: "60s"

x-logs: &logs
  output: [stdout, stderr]

x-watch: &watch
  include:
    - "**/*.go"
    - "**/*.yml"
    - "**/*.yaml"
  ignore:
    - ".git/**"
    - ".idea/**"
    - "vendor/**"
    - "**/*_test.go"
    - "**/*_mock.go"
  shared:
    - "pkg/common/**"
    - "pkg/rpc/**"
  debounce: 1s

Services

Services are organized into tiers. fuku starts all services in a tier, waits for readiness, then moves to the next tier.

fuku.yaml (continued)
services:
  # Foundation — auth, users, shared infrastructure
  auth-service:
    dir: auth-service
    tier: foundation
    readiness:
      <<: *readiness-tcp
      address: "localhost:3001"
    logs: *logs

  users-service:
    dir: users-service
    tier: foundation
    readiness:
      <<: *readiness-tcp
      address: "localhost:3002"
    logs: *logs
    watch: *watch

  inventory-service:
    dir: inventory-service
    tier: foundation
    readiness:
      <<: *readiness-tcp
      address: "localhost:3003"
    logs: *logs

  # Core — main business entities
  catalog-service:
    dir: catalog-service
    tier: core
    readiness:
      <<: *readiness-tcp
      address: "localhost:3004"
    logs: *logs
    watch: *watch

  orders-service:
    dir: orders-service
    tier: core
    readiness:
      <<: *readiness-tcp
      address: "localhost:3005"
    logs: *logs

  cart-service:
    dir: cart-service
    tier: core
    readiness:
      <<: *readiness-tcp
      address: "localhost:3006"
    logs: *logs

  # Platform — payments, shipping, notifications
  payments-service:
    dir: payments-service
    tier: platform
    readiness:
      <<: *readiness-tcp
      address: "localhost:3007"

  shipping-service:
    dir: shipping-service
    tier: platform
    readiness:
      <<: *readiness-tcp
      address: "localhost:3008"

  notifications-service:
    dir: notifications-service
    tier: platform
    readiness:
      <<: *readiness-tcp
      address: "localhost:3009"

  search-service:
    dir: search-service
    tier: platform
    readiness:
      <<: *readiness-http
      url: "http://localhost:3010/health"

  # Background — workers, async processing
  worker:
    dir: worker
    tier: background
    readiness:
      <<: *readiness-log
      pattern: "Worker started"
    logs: *logs

  # Edge — client-facing API gateways
  storefront-api:
    dir: storefront-api
    tier: edge
    readiness:
      <<: *readiness-http
      url: "http://localhost:3000/health"
    logs: *logs
    watch: *watch

  backoffice-api:
    dir: backoffice-api
    tier: edge
    readiness:
      <<: *readiness-http
      url: "http://localhost:3100/health"
    logs: *logs

  storefront-web:
    dir: storefront-web
    tier: edge
    command: npm run dev
    readiness:
      <<: *readiness-http
      url: "http://localhost:4000"
    logs: *logs
    watch:
      include: ["src/**"]
      debounce: 500ms

  backoffice-web:
    dir: backoffice-web
    tier: edge
    command: npm run dev
    readiness:
      <<: *readiness-http
      url: "http://localhost:4100"
    logs: *logs

Profiles

Profiles let you run subsets of services. Use "*" to include everything, or list specific services.

fuku.yaml (continued)
profiles:
  default: "*"

  # Storefront and its direct dependencies
  storefront:
    - storefront-web
    - storefront-api
    - auth-service
    - users-service
    - catalog-service
    - cart-service
    - inventory-service
    - search-service

  # Checkout flow
  checkout:
    - storefront-web
    - storefront-api
    - auth-service
    - users-service
    - cart-service
    - orders-service
    - payments-service
    - shipping-service
    - inventory-service
    - notifications-service
    - worker

  # Backoffice
  backoffice:
    - backoffice-web
    - backoffice-api
    - auth-service
    - users-service
    - orders-service
    - inventory-service
    - catalog-service

concurrency:
  workers: 10

retry:
  attempts: 5
  backoff: 1s

logs:
  buffer: 1024

logging:
  level: info
  format: console

Running

terminal
# Start everything
fuku

# Start only the storefront profile
fuku run storefront

# Start checkout without TUI
fuku run checkout --no-ui

Key Patterns

YAML Anchors for DRY Config

Prefix anchor names with x- to keep them separate from fuku config keys. Use <<: *anchor to merge and override individual fields like address or url.

Tier Ordering

Think about which services other services depend on. Put those in earlier tiers. A common pattern:

  • foundation — auth, users, inventory
  • core — main business entities (catalog, orders, cart)
  • platform — payments, shipping, notifications, search
  • background — workers, async processors
  • edge — APIs, frontends

Custom Commands

By default, fuku runs make run in each service directory. The command option lets you override this with any shell command — useful for running the same codebase in a different mode, spinning up tooling, or wrapping a service with extra steps.

For example, you can add a Swagger UI alongside your backend without changing the backend code. Define a second service pointing at the same directory with a custom command:

fuku.yaml
services:
  backend:
    dir: backend
    tier: core
    readiness:
      type: http
      url: "http://localhost:3000/health"

  backend-swagger:
    dir: backend
    tier: edge
    command: >-
      make swagger &&
      docker run --rm --name backend-swagger
      -p 8080:8080
      -v $(pwd)/docs/swagger.json:/usr/share/nginx/html/swagger.json
      -v $(pwd)/docs/nginx.conf:/etc/nginx/conf.d/default.conf
      nginx:alpine
    readiness:
      type: http
      url: "http://localhost:8080"

profiles:
  default: [backend]
  docs: [backend, backend-swagger]

Run fuku run docs and you get your backend plus live Swagger UI at localhost:8080 — all managed by fuku.

Single containers work well with command because fuku owns the process — it can stop, restart, and check readiness of each container individually. Avoid running Docker Compose inside fuku: compose manages its own process tree, so fuku loses visibility into individual container health, logs get duplicated, and hot-reload restarts the entire stack instead of a single service.

For infrastructure like databases and queues, run docker compose up separately and let fuku manage your application services on top.

Selective Watch

Only enable watch on services you actively modify. Watching all services causes unnecessary restarts during branch switches or pulls. See Troubleshooting for details.

Readiness Check Types

  • TCP — best for gRPC services. Checks if the port is accepting connections.
  • HTTP — best for REST APIs. Hits a health endpoint.
  • Log — best for workers and services without a network interface. Matches a log pattern.