Kubernetes liveness and readiness probes for Phoenix (and Plug).

Default endpoints:

  • GET /health/live — process is up (200 ok)
  • GET /health/ready — app can accept traffic (200 ok or 503 unavailable)

When a :repo is configured, readiness runs SELECT 1 through Ecto.Adapters.SQL.

Installation

def deps do
  [
    {:phoenix_healthy, "~> 0.1.0"}
  ]
end

Usage

Router (Phoenix)

defmodule MyAppWeb.Router do
  use MyAppWeb, :router
  import PhoenixHealthy.Router

  phoenix_healthy("/health", repo: MyApp.Repo)
end

This exposes GET /health/live and GET /health/ready.

Or configure the repo once:

# config/config.exs
config :phoenix_healthy, repo: MyApp.Repo
import PhoenixHealthy.Router
phoenix_healthy("/health")

Endpoint plug

Place it near the top of endpoint.ex so probes skip the rest of the pipeline (sessions, parsers, request logs):

defmodule MyAppWeb.Endpoint do
  use Phoenix.Endpoint, otp_app: :my_app_web

  plug PhoenixHealthy.Plug, repo: MyApp.Repo
  # ...
end

Your own controller (Swagger, custom plugs)

defmodule MyAppWeb.HealthController do
  use MyAppWeb, :controller
  use PhoenixHealthy, repo: MyApp.Repo
end
pipeline :health do
  plug :accepts, ["html", "text", "json"]
end

scope "/health", MyAppWeb do
  pipe_through :health
  get "/live", HealthController, :live
  get "/ready", HealthController, :ready
end

Options

OptionDefaultDescription
:reponilEcto repo used for the default readiness check
:path"/health"Base path for PhoenixHealthy.Plug
:live_path"live"Liveness segment
:ready_path"ready"Readiness segment
:livealways okCustom liveness probe (() -> probe_result) or MFA
:readyrepo check, else okCustom readiness probe (() -> probe_result) or MFA
:ok_body"ok"Body for a passing probe
:error_body"unavailable"Body for a failing probe

A probe may return :ok, true, :error, false, or {:error, reason}.

Custom readiness (for example Redis + DB):

phoenix_healthy("/health",
  ready: fn ->
    with :ok <- PhoenixHealthy.Checks.ecto(MyApp.Repo),
         :ok <- MyApp.Redis.ping() do
      :ok
    end
  end
)

Kubernetes

livenessProbe:
  httpGet:
    path: /health/live
    port: http
readinessProbe:
  httpGet:
    path: /health/ready
    port: http