Build And Deploy
Control Plane
Expose liveness, readiness, metrics, and Go diagnostics outside application routes.
Enable probes in app config
Generated apps do not include same-handler control-plane routes by default. Add an empty control-plane config when the app should expose framework-owned operational endpoints on the same handler as the app:
return lazyapp.New(lazyapp.Config{
Name: "sample_app",
Drawer: Draw,
Public: app.Public,
Views: app.Views,
Dependencies: Dependencies,
ControlPlane: lazycontrolplane.Config{},
})
The empty config exposes:
GET /livez
GET /readyz
When the control plane is mounted on the app listener, control-plane routes are
checked before application routes. If the app also draws /livez, the
control-plane route wins.
Use a separate address
ListenAndServe activates the default control plane when
CONTROL_PLANE_ADDR is set:
ADDR=0.0.0.0:8080 CONTROL_PLANE_ADDR=127.0.0.1:9090 ./app
When CONTROL_PLANE_ADDR differs from the app address, ListenAndServe starts
a second HTTP server for the control plane. The public app server then serves
only application traffic.
If CONTROL_PLANE_ADDR matches ADDR, PORT, or the default
127.0.0.1:3000, GoLazy mounts the control plane into the app server instead
of trying to bind the same port twice:
CONTROL_PLANE_ADDR=3000 ./app
If CONTROL_PLANE_ADDR is unset, production ListenAndServe does not mount
control-plane endpoints on the public app listener, even when the app config
builds a control plane. This keeps liveness, readiness, metrics, and diagnostics
off public routes by default.
Add readiness checks
Readiness checks receive the request context and return an error when the app is not ready:
ControlPlane: lazycontrolplane.Config{
Readiness: []lazycontrolplane.ReadinessCheck{{
Name: "database",
Check: func(ctx context.Context) error {
return db.PingContext(ctx)
},
}},
},
/readyz returns 503 Service Unavailable when a check fails.
Attach metrics and pprof
Metrics are opt-in:
ControlPlane: lazycontrolplane.Config{
Metrics: metricsHandler,
},
That registers GET /metrics. GoLazy does not add a Prometheus dependency for
you; pass a handler from the exporter you choose.
Go diagnostics are also opt-in:
ControlPlane: lazycontrolplane.Config{
Pprof: true,
},
That registers /debug/pprof/ and the standard pprof subpaths. Prefer a
separate CONTROL_PLANE_ADDR before enabling diagnostics in production.
Serve manually
If you need a custom server lifecycle, instantiate the control plane yourself:
plane := lazycontrolplane.New(lazycontrolplane.Config{})
server := &http.Server{
Addr: "127.0.0.1:9090",
Handler: plane,
}
When you manage the server manually, lazyapp.ListenAndServe is not responsible
for starting that control-plane server.
Development endpoints
Apps started by lazy are built with the lazydev tag and receive a separate
internal CONTROL_PLANE_ADDR. In that mode GoLazy adds development-only
endpoints such as GET /routes, GET /cache, POST /cache/on,
POST /cache/off, POST /views, and POST /_golazy/open-editor.
Those endpoints are not part of production builds. Read Lazydev Mode for the development-only surface.