HTTP/1.1 + HTTP/2 + HTTP/3 (QUIC) adapter for Phoenix applications.

Gale replaces Bandit for HTTP/1.1 and HTTP/2, and adds HTTP/3 over QUIC on UDP.

Installation

# mix.exs
def deps do
  [{:gale, "~> 0.1"}]
end

Quick Start

1. Configure Phoenix Endpoint

# config/config.exs
config :my_app, MyAppWeb.Endpoint,
  adapter: Gale.PhoenixAdapter

Or use the generator:

mix gale.phoenix

2. Enable HTTP/3 (optional)

# config/dev.exs or config/runtime.exs
config :my_app, MyAppWeb.Endpoint,
  https: [port: 443, certfile: "...", keyfile: "..."],
  http3: true

3. Open Firewall

# TCP for HTTP/1.1, HTTP/2
firewall-cmd --add-port=443/tcp

# UDP for HTTP/3
firewall-cmd --add-port=443/udp

Performance

Protocolreq/svs HTTP/1.1
HTTP/1.1~2,000
HTTP/2~2,5001.25×
HTTP/3 (7 streams)~825,000412×

Configuration

Development

# config/dev.exs
config :my_app, MyAppWeb.Endpoint,
  http: [ip: {127, 0, 0, 1}, port: 4000],
  https: [port: 4001, certfile: "...", keyfile: "..."],
  http3: true

Generate self-signed certs:

mix phx.gen.cert

Production

# config/runtime.exs
config :my_app, MyAppWeb.Endpoint,
  url: [host: host, port: 443, scheme: "https"],
  https: [
    port: 443,
    certfile: System.fetch_env!("SSL_CERT_PATH"),
    keyfile: System.fetch_env!("SSL_KEY_PATH")
  ],
  http3: true,
  server: true

How It Works

Browser  HTTP/1.1  Bandit  Phoenix Endpoint
          HTTP/2  Bandit  Phoenix Endpoint
          HTTP/3  QUIC  Phoenix Endpoint

LiveView/WebSocket  TCP  Bandit (unchanged)

Gale sends alt-svc: h3="host:443" headers so browsers upgrade to HTTP/3.

What Stays on Bandit

  • LiveView websockets
  • Channels
  • HTTP/2
  • The Plug pipeline

Architecture

ComponentProtocolBackend
HTTP/1.1TCPBandit
HTTP/2TCPBandit
HTTP/3UDP:quic_h3
QPACKGale Zig NIF
WebSocketTCPBandit

Why HTTP/3?

  • 0-RTT connection establishment
  • Multiplexing without head-of-line blocking
  • Better on lossy networks (mobile, WiFi)
  • Connection migration (IP changes don't break connection)

Troubleshooting

Browser doesn't upgrade to HTTP/3

  1. Check UDP 443 is open
  2. Verify valid SSL certificates
  3. Check alt-svc header in responses
  4. Ensure :quic_h3 started successfully

See Also