Microservices
ZinTrust includes a microservices runtime and a recommended zin-based scaffolding workflow.
This guide combines the practical material that was previously split across multiple pages: service generation, discovery, registration, authentication, tracing, database isolation, and container-oriented workflows.
For the runtime file layout, manifest format, standalone boot flow, Cloudflare Worker configuration, and config override model, see microservices-runtime-contract.md.
Recommended CLI Workflow
The recommended way to start a microservice-oriented project is:
# Create a microservice-focused project
zin new commerce-platform --template microservice --database postgresql --no-interactive
# Add services inside the project
zin add service users --domain ecommerce --port 3001 --database shared --auth api-key --no-interactive
zin add service orders --domain ecommerce --port 3002 --database shared --auth api-key --no-interactive
zin add service payments --domain ecommerce --port 3003 --database isolated --auth jwt --no-interactiveUse this flow when you want services to live inside the main project under src/services/....
What ZinTrust Supports Today
The current microservices implementation includes:
- Filesystem discovery via
MicroserviceBootstrap - In-memory registration and service calls via
MicroserviceManager - Optional service-to-service auth via
ServiceAuthMiddleware - Optional request tracing via
RequestTracingMiddleware - Health helpers such as
HealthCheckHandlerandServiceHealthMonitor - Project and service scaffolding through the
zinCLI, including service-local Cloudflare Workerwrangler.jsoncfiles
Terminology note:
- In this guide, Cloudflare Worker means the serverless request runtime used with Wrangler and Cloudflare Workers.
- ZinTrust worker means a background job worker from the ZinTrust workers package.
- They are different systems and should not be treated as interchangeable.
Enable Microservices Mode
Microservices mode is controlled by environment variables:
MICROSERVICES=trueenables discovery and bootstrappingENABLE_MICROSERVICES=trueexists as a legacy/test fallbackSERVICES=name1,name2acts as an allow-list when set
Service Layout and service.config.json
MicroserviceBootstrap discovers services under:
src/services/<domain>/<service>/service.config.json
Each discovered service is registered with the manager using its name and domain.
Example structure
src/services/
ecommerce/
users/
service.config.json
orders/
service.config.jsonExample config
{
"name": "users",
"domain": "ecommerce",
"version": "1.0.0",
"port": 3001,
"description": "Users microservice",
"dependencies": ["orders"],
"healthCheck": "/health",
"database": { "isolation": "shared", "migrations": true },
"auth": { "strategy": "none" },
"tracing": { "enabled": false, "samplingRate": 1 }
}Notes:
portis optional; if missing, a port is assigned based on discovery order.healthCheckdefaults to/healthif not provided.domainis derived from the directory path and must match your layout.
Discovery and Registration
Service discovery in ZinTrust is currently a filesystem plus in-memory registry model:
MicroserviceBootstrapscans the service directoriesMicroserviceManagerholds registered services in memory
Bootstrapping discovery:
import { MicroserviceBootstrap } from '@zintrust/core';
await MicroserviceBootstrap.getInstance().initialize();What this does:
- Returns early if microservices are disabled.
- Discovers services from the configured services directory.
- Registers them with
MicroserviceManager. - Logs migration-related information when
database.migrationsis enabled.
Allow-list via SERVICES
If SERVICES is set as a comma-separated list, the framework treats it as an allow-list:
- Services not listed are skipped during registration.
- If
SERVICESis empty, all discovered services are eligible.
Inter-Service Communication
Use MicroserviceManager.callService() to call a registered service:
import { MicroserviceManager } from '@zintrust/core';
const manager = MicroserviceManager.getInstance();
await manager.startService('users');
const response = await manager.callService('users', {
method: 'GET',
path: '/health',
timeout: 5_000,
});Important behavior:
- The manager throws if the service is not registered.
- The manager throws if the service is not in
runningstatus. callService()usesfetch()and validates the target URL.
Health Checks
ZinTrust does not automatically add a health route to each service. You must expose one and point healthCheck to it.
For convenience, the framework includes HealthCheckHandler:
import { HealthCheckHandler } from '@zintrust/core';
const health = HealthCheckHandler.create('users', '1.0.0', 3001, 'ecommerce');
// Mount health.handle at GET /healthFor polling multiple services from a monitoring process, use ServiceHealthMonitor.
Service-to-Service Authentication
ServiceAuthMiddleware supports:
api-keyjwtnonecustom
Production guidance:
- Configure
SERVICE_API_KEYorSERVICE_JWT_SECRET. - Add the middleware to the service request pipeline.
Request Tracing
RequestTracingMiddleware can:
- Attach and log
x-trace-idand related headers on incoming requests - Provide an
injectHeaders()helper for outgoing calls
Propagation is not automatic in callService(); pass the headers explicitly.
Database Isolation Strategies
Shared database
Use a single database with service-specific schemas:
{
"database": {
"isolation": "shared",
"migrations": true
}
}Benefits:
- Lower infrastructure cost
- Easier operational management
- Optional cross-service joins when needed
Isolated database
Give each service its own database:
{
"database": {
"isolation": "isolated",
"migrations": true
}
}Benefits:
- Stronger service boundaries
- Independent scaling and migration strategy
- Cleaner ownership per service
Environment Configuration
MICROSERVICES=true
SERVICES=users,orders,payments
MICROSERVICES_TRACING=true
MICROSERVICES_TRACING_RATE=0.5
DATABASE_ISOLATION=sharedFor the full config surface, see config-microservices.md.
Container and Deployment Notes
For microservice projects generated with zin, you can containerize each service using the standard Docker workflow used elsewhere in ZinTrust:
- add service-level Dockerfiles where needed
- run
docker-composeor your deployment platform of choice - keep service config and environment variables aligned with each service boundary
The main recommended developer workflow remains the zin CLI for project and service scaffolding.