Gale
Gale adds HTTP/3 (QUIC) support to your Phoenix applications with a simple drop-in adapter. Built on Bandit for HTTP/1.1/HTTP/2, with :quic_h3 for HTTP/3 and a Zig NIF for maximum QPACK performance.
Why Gale?
| Feature | Without Gale | With Gale |
|---|---|---|
| HTTP/1.1 | ✅ | ✅ |
| HTTP/2 | ✅ | ✅ |
| HTTP/3 | ❌ | ✅ |
| Performance (7 streams) | — | 412× faster |
| QPACK NIF | ❌ | ✅ |
HTTP/3 with 7 parallel streams achieves ~825K req/s — 412× faster than HTTP/1.1 on localhost.
Installation
def deps do
[
{:gale, "~> 0.1"}
]
end
Then add the adapter to your Phoenix endpoint:
# config/config.exs
config :my_app, MyAppWeb.Endpoint,
adapter: Gale.PhoenixAdapter
Quick Start
Phoenix Application
# config/config.exs
config :my_app, MyAppWeb.Endpoint,
adapter: Gale.PhoenixAdapter,
http: [port: 4000],
https: [port: 443, ...],
http3: true
Plug Application
defmodule MyApp do
use Plug.Builder
plug :match
plug :dispatch
get "/" do
send_resp(conn, 200, "Hello from Gale!")
end
end
# In your supervision tree
children = [
{Gale.Plug, plug: MyApp, port: 4000}
]
HTTP/3 Performance
┌─────────────────────────────────────────────────────────────┐
│ Performance Comparison │
├────────────────────┬──────────────┬────────────────────────┤
│ Protocol │ req/s │ vs HTTP/1.1 │
├────────────────────┼──────────────┼────────────────────────┤
│ HTTP/1.1 │ ~2,000 │ 1× │
│ HTTP/3 (single) │ ~2,500 │ 1.25× │
│ HTTP/3 (7 streams) │ ~825,000 │ 412× │
└────────────────────┴──────────────┴────────────────────────┘
HTTP/3's parallel streams eliminate head-of-line blocking, delivering massive throughput gains.
Features
Server
- HTTP/1.1, HTTP/2 via Bandit (unchanged)
- HTTP/3 via
:quic_h3(UDP/QUIC) - Phoenix adapter — drop-in replacement
- Plug adapter — for non-Phoenix apps
- WebSocket support
- WebTransport support
- QPACK NIF — 2.5× faster encoding via Zig
Client
- Gale.HTTP — unified HTTP client
- Gale.Finch — Finch-compatible with HTTP/3
- Gale.Hackney — Hackney-compatible
- Gale.Req — Req plugin
Configuration
Phoenix Endpoint
# config/config.exs
config :my_app, MyAppWeb.Endpoint,
adapter: Gale.PhoenixAdapter
# 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
HTTP/3 Options
config :my_app, MyAppWeb.Endpoint,
http3: [
port: 443,
max_idle_timeout: 60_000,
max_concurrent_bidi_streams: 100,
max_concurrent_uni_streams: 10
]
Plug Options
{Gale.Plug,
plug: MyPlug,
port: 4000,
scheme: :http,
ip: {127, 0, 0, 1}}
{Gale.Plug,
plug: MyPlug,
port: 443,
scheme: :https,
certfile: "cert.pem",
keyfile: "key.pem",
http3: true}
CLI
# Install Gale CLI
mix gale.install
# Make HTTP requests
gale get https://example.com
gale get https://example.com --http3
# Hash files
gale hash ./file --algo blake3
# Check version
gale version
Architecture
┌─────────────────────────────────────────────────────────────┐
│ CLIENTS │
│ Browser ─── curl ─── Req ─── Finch ─── Hackney │
└────────────────────────┬──────────────────────────────────┘
│
┌───────────────┼───────────────┐
│ │ │
▼ ▼ ▼
┌─────────────────┐ ┌─────────┐ ┌─────────────────────────┐
│ HTTP/1.1 │ │ HTTP/2 │ │ HTTP/3 │
│ TCP │ │ TLS │ │ QUIC/UDP │
└────────┬────────┘ └────┬────┘ └───────────┬─────────────┘
│ │ │
└───────────────┼─────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Gale / Bandit │
│ Phoenix Adapter │ Plug Adapter │ QPACK NIF │ HTTP/3 │
└─────────────────────────────────────────────────────────────┘
Requirements
- Elixir 1.17+
- OTP 27+
- Zig 0.16+ (for building NIFs)
Benchmarks
Run locally:
mix deps.get
mix gale.build
mix bench
Results saved to benchmark/RESULTS.md.
Documentation
- Phoenix Guide — Phoenix integration
- Plug Guide — Plug integration
- HexDocs — Full API documentation
Ecosystem
gale — Phoenix HTTP/3
ingot — Iroh + Zenoh cluster (Hex: `ingot_cluster`)
dusk — Zenoh + Iroh cluster
orian — BLAKE3 / S3 / S5 storage
zeiroh — Phoenix FLAME overlay
Migration
Bandit → Gale
# 1. Add to mix.exs
{:gale, "~> 0.1"}
# 2. Update config
config :my_app, MyAppWeb.Endpoint,
adapter: Gale.PhoenixAdapter
# 3. Enable HTTP/3 (optional)
config :my_app, MyAppWeb.Endpoint,
http3: true
Cowboy → Gale
# Before
{Bandit, plug: MyPlug, port: 4000}
# After
{Gale.Plug, plug: MyPlug, port: 4000}
License
MIT © Niranjan Aryan