A hundred services on one laptop means a hundred ports, and the easiest way to lose a morning is two services that want the same one. The tdk-erp-system example keeps the ports in predictable blocks, one block per domain, and TDK CLI handles the cases where a default is already taken.
The blocks
Each domain's services take ports from their own range. The README lists them, and the ones I checked follow a clear pattern:
- Finance backends use 4010 to 4024, and its dashboard uses 3010.
- HR backends start at 4100, and its portal uses 3020.
- Inventory backends start at 4200.
- Sales backends start at 4300.
- Analytics backends start at 4600, and its console uses 3070.
Frontends use the 3000 range, and backends use the 4000 range. A service's port is written in its service.json, so you can see where it sits by reading the file.
Why blocks help
When a service fails, the port tells you which domain it belongs to. When you add a service, the next free number in its domain's block is obvious. And a dashboard full of mixed ports is harder to read than one where each domain has its own range.
When a port is taken
TDK checks the default ports for its shared infrastructure, such as the proxy and Postgres. If one is taken, it chooses a free port from a fallback range and prints the choice. For example, when Postgres's default was in use during a test run, TDK used 15432 from a fallback range of 15432 to 15532.
The printed choice matters. Read it on every start, because a service that expects the default may need the new value.
Overriding a port
To pin a port, set its environment variable before you start:
TDK_POSTGRES_PORT=5432 tdk up
Other overrides follow the same pattern, including TDK_HTTP_PORT and TDK_HTTPS_PORT for the proxy. Set them when a tool outside TDK expects a fixed address.
Checking a port
The README links each service's health route on its port, so you can check a service with a browser or curl. For a machine-readable answer, use:
tdk status --json
It reports readiness and URLs, so you do not need to remember which port belongs to which service.
Summary
Ports in the ERP example are grouped by domain, so the number tells you where a service belongs. TDK moves to a free port when a default is taken and prints the choice. Pin a port only when something outside TDK needs it, and check addresses with tdk status --json.
Top comments (1)
TDK CLI describes each service in a service.json file, generates the Docker, routing, and Tilt files from it, and starts the whole stack with tdk up. Three features help with fragility:
tdk doctor --json checks whether the machine can run the stack, including whether a container runtime is reachable.
tdk up main --dry-run shows the plan, the ports, and the start order without starting anything.
Drift checks compare the generated files with saved snapshots before startup, so a hand-edited Dockerfile or Tiltfile blocks the start and names the file.
It is for local development. Production deployment stays with tools such as Helm, Argo CD, or Kustomize. It also supports an MCP server, tdk mcp, if you want an agent to start the stack and read its readiness directly.