Installation

Copy Markdown

Dependencies

Add supabase_realtime and supabase_potion to your mix.exs:

def deps do
  [
    {:supabase_potion, "~> 0.7"},
    {:supabase_realtime, "~> 0.5.0"} # x-release-please-version
  ]
end

Then fetch dependencies:

mix deps.get

Creating a Client

Create a %Supabase.Client{} struct using Supabase.init_client/3:

{:ok, client} = Supabase.init_client(
  "https://your-project.supabase.co",
  "your-api-key"
)

You can also pass additional options as a third argument:

{:ok, client} = Supabase.init_client(
  "https://your-project.supabase.co",
  "your-api-key",
  %{access_token: "user-jwt-token"}
)

The client struct holds your project URL, API key, and derived service URLs (auth, storage, realtime, etc.). It is passed directly to the Realtime supervisor as the :client option.

Defining a Realtime Module

Create a module that uses Supabase.Realtime and implements the handle_event/1 callback:

defmodule MyApp.Realtime do
  use Supabase.Realtime

  def start_link(opts \\ []) do
    Supabase.Realtime.start_link(__MODULE__, opts)
  end

  @impl true
  def handle_event({:postgres_changes, operation, payload}) do
    IO.inspect({operation, payload}, label: "DB change")
    :ok
  end

  @impl true
  def handle_event({:broadcast, event, payload}) do
    IO.inspect({event, payload}, label: "Broadcast")
    :ok
  end

  @impl true
  def handle_event({:presence, event, payload}) do
    IO.inspect({event, payload}, label: "Presence")
    :ok
  end
end

The use Supabase.Realtime macro sets up a Supervisor that starts three child processes: the WebSocket Connection, the Channel Registry, and the Channel Store.

Supervision Tree Setup

Add your Realtime module to your application supervisor:

defmodule MyApp.Application do
  use Application

  def start(_type, _args) do
    {:ok, client} = Supabase.init_client(
      System.fetch_env!("SUPABASE_URL"),
      System.fetch_env!("SUPABASE_KEY")
    )

    children = [
      {MyApp.Realtime, client: client}
    ]

    opts = [strategy: :one_for_one, name: MyApp.Supervisor]
    Supervisor.start_link(children, opts)
  end
end

Configuration Options

All options are passed to start_link/2:

OptionTypeDefaultDescription
:client%Supabase.Client{}requiredThe Supabase client struct
:nameatommodule nameProcess registration name
:heartbeat_intervalinteger (ms)30000How often to send heartbeat pings. Keeps the WebSocket alive and detects dead connections.
:reconnect_after_msfunctionexponential backoffA function (attempts -> ms) that controls the delay between reconnection attempts. The default doubles on each try, up to 10 seconds.
:http_fallbackbooleanfalseWhen true, broadcast messages are sent over HTTP if the WebSocket is down. Other message types are buffered.
:access_token_fnfunction or MFAnilA zero-arity function returning {:ok, token} or {:error, reason}. Called before each WebSocket upgrade to get a fresh token.
:paramsmap%{}Extra query parameters appended to the WebSocket URL. Useful for server-side logging or routing.

Example with all options

{MyApp.Realtime,
  client: client,
  heartbeat_interval: :timer.seconds(15),
  reconnect_after_ms: fn tries -> min(:timer.seconds(10), :timer.seconds(tries)) end,
  http_fallback: true,
  access_token_fn: fn -> MyApp.Auth.get_fresh_token() end,
  params: %{log_level: "debug"}}