Skip to Content
ConfigurationLifecycle & Hooks

Lifecycle & Hooks

Nanokit provides a powerful engine to manage the lifecycle of your services, from the initial provisioning of dependencies to graceful teardown.

Understanding these hooks is essential for managing database migrations, complex build steps, and service discovery updates.


Provisioning Hook (provisioning.install)

The provisioning.install command is designed for one-time initialization of a service. It is specifically optimized for distributed environments where multiple replicas might share the same persistent storage.

How it works

  1. Host-Side Execution: The command runs on the host (or inside a temporary bootstrap container) before the service containers start.
  2. Atomic Locking: Nanokit uses a sentinel file located in the service’s primary volume to track installation status.
  3. Prevention of Race Conditions: If multiple replicas or environments share the same volume, Nanokit ensures only one process performs the installation.
services: api: runtime: node provisioning: # Executed only once if node_modules is missing or sentinel is absent # Can also be defined globally in the 'node' runtime install: "npm install --prefer-offline"

[!TIP] Use provisioning.install for heavy operations like npm install, composer install, or downloading large binary dependencies that should persist across container restarts.


Service Hooks (hooks)

Service hooks are executed relative to the container lifecycle. These are defined under the hooks key in your service configuration.

PhaseContextTypical Use Case
prestartHost/ProviderDatabase migrations (prisma migrate), build steps (nx build), config generation.
poststartHost/ProviderWarm-up scripts, registration in external service discovery.
prestopContainerGraceful session flushing, unregistering from load balancers.
poststopHost/ProviderCleanup of temporary files, logging teardown events.

Example: Database Migrations

The prestart hook is the recommended place for running database migrations. Nanokit ensures all required databases are up and healthy before triggering the hook.

services: web: runtime: node hooks: prestart: "npx prisma migrate deploy"

Example: Build Step Before Container Start

Services that run compiled output (e.g. node dist/...) need their source built before the container can start. Use prestart to auto-build these services — this is especially useful for containerized backend services where the Docker image runs pre-compiled JavaScript.

services: api-gateway: runtime: node start: node dist/apps/api-gateway/main.js hooks: prestart: "npx nx build api-gateway --skip-nx-cache"

The prestart hook runs on the host before the container is created, ensuring the compiled output is ready when the container starts. This approach keeps build tooling (Nx, Webpack, TypeScript) out of the container image, resulting in leaner production images.

[!TIP] For monorepo backends, define a prestart build hook on each service that runs from dist/. Nanokit executes these hooks automatically during nkapp up, eliminating the need for manual rebuilds.

Example: Post-Startup Notification

You can use poststart to trigger external webhooks or internal logging once a service is live.

services: worker: runtime: node hooks: poststart: "curl -X POST https://status.internal/v1/event -d '{\"service\": \"worker\", \"status\": \"online\"}'"

Deployment Hooks

While service hooks manage the container lifecycle, deployment hooks manage the orchestration process itself.

deploy.prepare

The prepare command runs on your local machine (or CI runner) immediately after code is synchronized but before the reconciler starts on the remote host. It is ideal for local build steps that need to be synced.

deploy: target: root@my-vps prepare: "npm run build:css && rsync -avz ./dist ./remote:/opt/nanokit/dist"

Environment Variables in Hooks

All hooks have access to standard Nanokit environment variables, allowing you to create context-aware scripts:

  • NANOKIT_SERVICE: Name of the current service.
  • NANOKIT_ENV: Current environment (e.g., stage, prod).
  • NANOKIT_PROJECT: Name of the project.
  • LIFECYCLE_PHASE: The name of the hook being executed.

Best Practices

  1. Idempotency: Ensure hooks can be run multiple times without side effects (especially prestart).
  2. Timeouts: Hooks that run for too long can block deployments. Offload heavy async tasks to background workers if possible.
  3. Error Handling: Non-zero exit codes in prestart or provisioning.install will halt the deployment for that service.