Deployment Overview
Zig produces statically-linked, single-binary executables with no runtime dependencies. This makes zzz applications straightforward to deploy — copy the binary, set environment variables, and run.
Production build
Section titled “Production build”Build an optimized release binary with:
zig build -Doptimize=ReleaseFastThe resulting binary is in zig-out/bin/. It is a self-contained executable that includes all compiled templates, static assets (if embedded), and vendored C libraries.
Build optimization modes
Section titled “Build optimization modes”| Flag | Description | Use case |
|---|---|---|
-Doptimize=ReleaseFast | Maximum runtime performance | Production servers |
-Doptimize=ReleaseSafe | Optimized with safety checks (bounds checking, overflow detection) | Staging, security-sensitive deployments |
-Doptimize=ReleaseSmall | Minimize binary size | Containers, embedded |
| (none) | Debug mode with full safety and debug info | Development only |
For most production deployments, ReleaseFast is recommended. Use ReleaseSafe if you prefer catching undefined behavior at the cost of a small performance overhead.
Setting the environment
Section titled “Setting the environment”Pass the target environment at build time with the -Denv option:
zig build -Doptimize=ReleaseFast -Denv=prodThe Environment enum recognizes these values:
| Value | Aliases | Description |
|---|---|---|
dev | development | Development mode (default) |
prod | production | Production mode |
staging | Staging/pre-production | |
testing | test | Test suite |
Environment configuration
Section titled “Environment configuration”zzz uses .env files and system environment variables for runtime configuration. The Env loader follows this precedence (highest to lowest):
- System environment variables (via
getenv) .env.{environment}entries (e.g.,.env.prod).enventries (base)
See the Environment Config page for full details.
Quick setup
Section titled “Quick setup”-
Create a
.envfile with your base configuration:Terminal window HOST=127.0.0.1PORT=4000DATABASE_URL=sqlite:data/app.db -
Create environment-specific overrides in
.env.prod:Terminal window HOST=0.0.0.0PORT=8080DATABASE_URL=postgres://deploy@db.internal:5432/myapp_prod -
Load and merge in your application:
const zzz = @import("zzz");const AppConfig = struct {host: []const u8,port: u16,database_url: []const u8,};const defaults = AppConfig{.host = "127.0.0.1",.port = 4000,.database_url = "sqlite:data/dev.db",};pub fn main() !void {var gpa = std.heap.GeneralPurposeAllocator(.{}){};const allocator = gpa.allocator();var result = try zzz.configInit(AppConfig, defaults, allocator, .{.environment = "prod",});defer result.env.deinit();const config = result.config;// config.host == "0.0.0.0" (from .env.prod)// config.port == 8080 (from .env.prod)}
Production checklist
Section titled “Production checklist”Before deploying to production, verify each of the following:
Build and binary
Section titled “Build and binary”- Build with
-Doptimize=ReleaseFast(orReleaseSafe) - Build with
-Denv=prod - Test the release binary locally before deploying
- Verify the binary runs without any shared library dependencies (
lddon Linux,otool -Lon macOS)
Configuration
Section titled “Configuration”- All secrets (API keys, database passwords, SMTP credentials) are provided via environment variables or
.env.prod, not hardcoded -
HOSTis set to0.0.0.0(to bind all interfaces) or the specific interface for your deployment -
PORTis set appropriately for your reverse proxy or load balancer -
DATABASE_URLpoints to the production database
Security
Section titled “Security”- Application is behind a reverse proxy (nginx, Caddy, etc.) that handles TLS termination
- Sensitive environment variables are not logged (the
Env.maskSensitivemethod automatically masks keys containingSECRET,PASSWORD,TOKEN,KEY,DATABASE_URL, orPRIVATE) - CORS, CSRF, and rate limiting middleware are configured for production
Monitoring
Section titled “Monitoring”- Health check endpoint is available (e.g.,
GET /health) - Application logs are directed to a persistent location or log aggregator
- Process manager (systemd, Docker, etc.) is configured to restart on failure
Deployment strategies
Section titled “Deployment strategies”The simplest approach. Copy the binary and run it:
# Buildzig build -Doptimize=ReleaseFast -Denv=prod
# Deployscp zig-out/bin/myapp server:/opt/myapp/ssh server 'cd /opt/myapp && PORT=8080 DATABASE_URL=postgres://... ./myapp'Use a process manager like systemd to keep it running:
[Unit]Description=My zzz applicationAfter=network.target
[Service]Type=simpleExecStart=/opt/myapp/myappWorkingDirectory=/opt/myappEnvironmentFile=/opt/myapp/.env.prodRestart=alwaysRestartSec=5
[Install]WantedBy=multi-user.targetsudo systemctl enable --now myappBuild a minimal container image. See the Docker page for complete examples.
docker build -t myapp:latest .docker run -p 8080:8080 --env-file .env.prod myapp:latestPlace the application behind nginx or Caddy for TLS termination and static file serving:
server { listen 443 ssl http2; server_name app.example.com;
ssl_certificate /etc/letsencrypt/live/app.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/app.example.com/privkey.pem;
location / { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme;
# WebSocket support proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; }}Database URLs
Section titled “Database URLs”The DatabaseUrl parser understands PostgreSQL and SQLite URL formats:
# PostgreSQLDATABASE_URL=postgres://user:password@host:5432/dbnameDATABASE_URL=postgresql://deploy@db.internal/myapp_prod
# SQLiteDATABASE_URL=sqlite:data/app.dbDATABASE_URL=data/app.db # bare filename treated as SQLiteThe parser is zero-allocation — all returned slices point into the original URL string. For PostgreSQL, toConninfo() generates a libpq-compatible connection string.
Next steps
Section titled “Next steps”- Environment Config — detailed guide to
.envfiles and theEnvmodule - Docker — containerize your zzz application
- Performance — tuning and benchmarking