API Gateway End-to-End Example
What this page gives you
This deep dive explains a fan-out gateway pattern with one edge cell and three independent backend cells.
Shipped example location on NetBSD:
/usr/share/examples/cellmgr/api-gateway
Topology and dependency graph
Cells in this stack:
api-gateway-app-a-httpd(backend A on8080)api-gateway-app-b-httpd(backend B on8081)api-gateway-app-c-httpd(backend C on8082)api-gateway-edge-nginx(public edge on80)
Dependency graph:
- backend cells have no upstream deps
- edge depends on all three backends
api-gateway-app-a-httpd, api-gateway-app-b-httpd, api-gateway-app-c-httpd -> api-gateway-edge-nginx
Operational meaning:
- each backend can be reconciled independently
- edge converges only after all required backends are present
Manifest deep dive
Backend cell manifests (api-gateway-app-*-httpd.cell)
All three backend manifests follow the same model:
CELL_CREATE_PROFILE="medium"- one reserved port per backend (
8080,8081,8082) CELL_SUPERVISE_CMD="/usr/libexec/httpd -I <port> -X -f -s <docroot>"CELL_DEPENDS_ON=""- healthcheck asserts backend
index.htmlfile exists
This is a good pattern for horizontally split stateless services.
Edge manifest (api-gateway-edge-nginx.cell)
Key fields:
CELL_CREATE_PROFILE="high"CELL_CREATE_RESERVED_PORTS="80"CELL_DEPENDS_ON="api-gateway-app-a-httpd,api-gateway-app-b-httpd,api-gateway-app-c-httpd"- supervise command runs nginx as
nginxuser
This manifest is where dependency fan-in is modeled.
Apply plans
- each backend
*.applywrites themed static HTML page into its own docroot - edge
api-gateway-edge-nginx.applywrites nginx routing config:/a/->127.0.0.1:8080/b/->127.0.0.1:8081/c/->127.0.0.1:8082
No volume manifests are used in this stack because content is static and per cell.
End-to-end deployment steps
Run commands as root (or prefix with doas).
- bootstrap host once (skip if already done)
- copy shipped example manifests
- inspect desired state
- run targeted dry-run
- apply stack
- verify runtime
- validate edge routing
- open
http://<host-ip>/a/ - open
http://<host-ip>/b/ - open
http://<host-ip>/c/
You should see three different backend pages routed through one public edge.
Modeling takeaways
- dependency fan-in on edge models gateway contracts clearly
- reserved ports prevent accidental port collision between service cells
- separate backend cells make per-service rollout and troubleshooting easier