Skip to content
cccskills
FreePublished on GitHub

deploy

Elixir/Phoenix deployment patterns — Dockerfile, fly.toml; Use when configuring Fly.io, Docker, CI/CD, health checks…

The English summary is being prepared. Showing the original description.

See how to install

Files included (3)

  • SKILL.md4.4 KB
  • references/docker-config.md2.9 KB
  • references/flyio-config.md1.6 KB

SKILL.md (original)

Review the instructions the agent will receive before you install.

Elixir/Phoenix Deployment Reference

Quick reference for deploying Elixir/Phoenix applications.

Iron Laws — Never Violate These

  1. Config at runtime, not compile time — Secrets in config.exs get baked into the release binary. Use runtime.exs with env vars so secrets are resolved at boot
  2. Graceful shutdown ≥ 60 seconds — Shorter timeouts kill in-flight requests and WebSocket connections mid-operation, causing data loss for users
  3. Health checks required — Without startup/liveness/readiness endpoints, orchestrators can't distinguish a booting node from a dead one, leading to cascading restarts
  4. SSL verification for database — Skipping verify: :verify_peer allows MITM attacks between your app and database; production data traverses the connection
  5. No CPU limits — The BEAM scheduler assumes it owns all cores; cgroups CPU limits cause scheduler collapse where the VM thinks it has more cores than it can use, leading to latency spikes
  6. Guard optional service credentials — runtime.exs runs whenever a release boots, including eval-based migration commands. Only require S3, Redis, and similar credentials when that integration is enabled

Quick Configuration

runtime.exs (Essential)

if config_env() == :prod do
  database_url = System.get_env("DATABASE_URL") || raise "DATABASE_URL is required"
  secret_key_base = System.get_env("SECRET_KEY_BASE") || raise "SECRET_KEY_BASE is required"
  host = System.get_env("PHX_HOST") || raise "PHX_HOST is required"

  config :my_app, MyApp.Repo,
    url: database_url,
    pool_size: String.to_integer(System.get_env("POOL_SIZE") || "10"),
    ssl: true,
    ssl_opts: [verify: :verify_peer]

  config :my_app, MyAppWeb.Endpoint,
    url: [host: host, port: 443, scheme: "https"],
    http: [ip: {0, 0, 0, 0}, port: String.to_integer(System.get_env("PORT") || "4000")],
    secret_key_base: secret_key_base,
    server: true
end

Guard Optional Services

Keep core boot secrets such as DATABASE_URL and SECRET_KEY_BASE required. Gate credentials for optional integrations behind the same feature switch that enables the integration:

s3_config =
  if System.get_env("STORAGE_BACKEND") == "s3" do
    [
      access_key_id:
        System.get_env("S3_ACCESS_KEY") ||
          raise("S3_ACCESS_KEY is required when STORAGE_BACKEND=s3"),
      secret_access_key:
        System.get_env("S3_SECRET_KEY") ||
          raise("S3_SECRET_KEY is required when STORAGE_BACKEND=s3")
    ]
  else
    []
  end

config :my_app, :s3_config, s3_config

This lets release tasks that do not use S3 start without S3 credentials while still failing fast when S3 is selected.

Health Check Plug

def call(%{path_info: ["health", "readiness"]} = conn, _opts) do
  case Ecto.Adapters.SQL.query(MyApp.Repo, "SELECT 1", []) do
    {:ok, _} -> send_resp(conn, 200, ~s({"status":"ok"})) |> halt()
    {:error, _} -> send_resp(conn, 503, ~s({"status":"error"})) |> halt()
  end
end

Quick Decisions

Platform Choice

NeedUse
Simple, managedFly.io
Enterprise, existing K8sKubernetes
Custom infrastructureDocker + your orchestrator

Resource Limits

ResourceRecommendation
CPUNO LIMITS (BEAM scheduler issues)
MemorySet limits (256Mi-512Mi typical)
Graceful shutdown≥ 60 seconds

Deployment Checklist

  • All secrets from environment variables in runtime.exs
  • Optional service credentials required only when their integration is enabled
  • server: true in endpoint config
  • SSL verification for database connections
  • Health endpoints: /health/startup, /health/liveness, /health/readiness
  • Graceful shutdown period ≥ 60 seconds
  • No CPU limits (memory limits only)
  • Migrations in deploy process

Asset Pipeline Notes

Phoenix 1.8 uses esbuild + tailwind (no Node.js required):

  • Config in config/config.exs under :esbuild and :tailwind
  • mix assets.deploy builds for production
  • mix assets.setup installs binaries on first run
  • Custom JS bundlers: configure in config/config.exs

References

For detailed patterns, see:

  • references/docker-config.md - Multi-stage Dockerfile, best practices
  • references/flyio-config.md - fly.toml, clustering, commands

Reviews

No reviews yet. Tell others what you thought.

Comments

No login needed. Share how it worked for you, ask a question, or note where it did not run.

No comments yet. Be the first to write one.

Comments are published right away. Do not include personal information such as email addresses or phone numbers. Up to 2 URLs.

0 / 1,000 characters

This form is protected by reCAPTCHA, and the Google Privacy Policy and Terms of Service apply.

More skills from this repository

Analyze a legacy app in any language before rewriting it in Elixir: inventory, features as goals, why each mechanism exists, runtime topology, external contracts. Use to start or refresh a rewrite.

The English summary is being prepared. Showing the original description.

oliver-kriska/claude-elixir-phoenix567Updated Oct 17, 2026

Design the idiomatic Elixir architecture for a rewrite: set the compatibility bar (ADR-000), consult phx specialists on open questions, then build contexts, ledger and ADRs. Use after /rewrite:analyze.

The English summary is being prepared. Showing the original description.

oliver-kriska/claude-elixir-phoenix567Updated Oct 17, 2026

Ash Framework — resources, actions, policies, aggregates; Use when generating resources via mix ash.codegen, editing…

The English summary is being prepared. Showing the original description.

oliver-kriska/claude-elixir-phoenix567Updated Oct 17, 2026

Ash Framework — resources, actions, policies, aggregates, calculations, AshPhoenix.Form, LiveView, migrations. Use when generating resources via mix ash.codegen, editing changes, checks, types, validations, or domain code interfaces.

The English summary is being prepared. Showing the original description.

oliver-kriska/claude-elixir-phoenix567Updated Oct 17, 2026

Compatibility alias for the Elixir/Phoenix plugin's LiveView assigns audit. Invoke explicitly with /lv:assigns.

The English summary is being prepared. Showing the original description.

oliver-kriska/claude-elixir-phoenix567Updated Oct 17, 2026

Inspect LiveView socket assigns for memory bloat — missing temporary_assigns, unused assigns, unbounded lists needing streams, memory estimates. Use when LiveView memory grows or you need to add temporary_assigns.

The English summary is being prepared. Showing the original description.

oliver-kriska/claude-elixir-phoenix567Updated Oct 17, 2026

See all skills by oliver-kriska

Report a problem with this skill