We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
From Health Score to Production: The Deploy Pipeline
Three-phase production deployment with doctrine-enforced quality gates
Prismatic Engineering
Prismatic Platform
The Three-Phase Doctrine
Deploying to production is the highest-stakes operation in software engineering. A bad deploy can take down a running system, corrupt data, or expose security vulnerabilities. The Prismatic Platform mitigates this risk through a three-phase deployment pipeline where each phase must pass before the next begins.
Phase 1: Pre-Deploy Validation
Before any code reaches production, it must pass three categories of checks:
Quality Gates
mix format --check-formatted # Code formatting
mix compile --warnings-as-errors --force # Zero-warning compilation
mix credo --strict # Static analysis
mix test --cover # Test suite with coverage
mix dialyzer # Type checking
All quality gates must pass. A single warning, a single failing test, or a type error blocks the deploy.
Doctrine Compliance
The platform's 18-pillar doctrine is validated by mix check.doctrines:
|--------|-------|-------------|
Security Scan
A security-specific scan checks for:
mix deps.audit)Health Score Gate
The platform's health score (computed by mix health.score) must meet the minimum threshold. The health score is a composite metric combining compilation health, test coverage, doctrine compliance, and documentation completeness.
Phase 2: Deployment via Fly.io
The platform runs on Fly.io, which provides zero-downtime deployments through rolling updates:
Build Process
# Build the Docker image
fly deploy --build-only
# The Dockerfile:
# 1. Installs Erlang/OTP and Elixir
# 2. Fetches and compiles dependencies
# 3. Compiles the umbrella application
# 4. Builds production assets (esbuild + tailwind)
# 5. Creates the Mix release
# 6. Copies the release to a minimal runtime image
Rolling Update Strategy
Fly.io deploys new instances before shutting down old ones:
2. Health check endpoint (/api/v1/health) is polled
3. Once the new VM responds with HTTP 200, traffic is routed to it
4. Old VM receives a SIGTERM and has 30 seconds to drain connections
5. Old VM is shut down
This ensures zero downtime -- at no point are zero instances serving traffic.
Release Configuration
# rel/env.sh.eex
export RELEASE_DISTRIBUTION=name
export RELEASE_NODE=prismatic@${FLY_APP_NAME}.internal
export ERL_AFLAGS="-proto_dist inet6_tcp"
The release is configured for IPv6 (required by Fly.io's internal network) and uses named distribution for potential clustering.
Phase 3: Post-Deploy Validation
After deployment, automated checks verify the release is healthy:
Smoke Tests
Four critical endpoints are tested within 60 seconds of deployment:
# Health endpoint (must respond with 200)
curl -f https://prismatic-prod.fly.dev/api/v1/health
# Landing page (must respond with 200)
curl -f https://prismatic-prod.fly.dev/
# Dashboard (must respond with 200, authenticated)
curl -f https://prismatic-prod.fly.dev/dashboard
# API status (must return valid JSON)
curl -f https://prismatic-prod.fly.dev/api/v1/status
Performance Verification
Response times are measured and compared against baselines:
If any metric exceeds 2x the baseline, an alert is triggered. If any metric exceeds 5x the baseline, automatic rollback is initiated.
Functional Verification
Key user journeys are tested end-to-end:
Rollback Strategy
If post-deploy validation fails, the pipeline initiates automatic rollback:
# Immediate rollback to previous release
fly releases rollback --app prismatic-prod
# Verify rollback succeeded
curl -f https://prismatic-prod.fly.dev/api/v1/health
Rollback is fast (typically under 30 seconds) because Fly.io retains the previous release image. The old VMs are restarted from the cached image without requiring a rebuild.
Rollback Triggers
|-----------|--------|--------|
The Deploy Command
The entire pipeline is orchestrated by the /deploy command:
# Full pipeline: validate + deploy + verify
just deploy-validate staging
# Production (requires confirmation)
just deploy-production
# Dry run (preview without executing)
just deploy-dry-run production
The command provides real-time progress output for each phase, with clear pass/fail indicators and timing information. A typical production deploy takes 4-6 minutes end-to-end: 1-2 minutes for validation, 2-3 minutes for deployment, and 30-60 seconds for post-deploy verification.
Deployment History
Every deployment is recorded with its validation results, timing, and outcome:
v546: 2026-03-25 14:32 UTC | staging | PASS | 4m 12s
v547: 2026-03-25 15:01 UTC | staging | PASS | 3m 58s
v548: 2026-03-25 15:45 UTC | prod | PASS | 5m 03s
This history enables trend analysis: are deploys getting slower? Are failures increasing? Which phase fails most often?
Ship with confidence. The pipeline catches what humans miss.