In volatile markets, every second counts. Your users don’t want to refresh—they want live prices, moving charts, and streaming data.
Phoenix LiveView makes this not just possible—but elegant.
No SPA. No JS frameworks. Just Elixir, sockets, and structured state.
Streaming Price Feeds in Real Time
Most financial APIs (Binance, Coinbase, Polygon.io) expose WebSocket feeds.
Use websockex
to consume them:
WebSockex.start_link(
"wss://stream.binance.com:9443/ws/btcusdt@trade",
__MODULE__,
%{}
)
Each message is a trade or price event. Forward it to your app via:
Phoenix.PubSub.broadcast(MyApp.PubSub, "btc:usd", {:price_update, payload})
Then in your LiveView:
def mount(_, _, socket) do
Phoenix.PubSub.subscribe(MyApp.PubSub, "btc:usd")
{:ok, assign(socket, latest_price: nil)}
end
def handle_info({:price_update, data}, socket) do
{:noreply, assign(socket, latest_price: data["p"])}
end
Boom: real‑time price updates, rendered automatically.
Live Streams: Constantly Updating Lists
Show recent trades with live_stream
:
def handle_info({:trade, trade}, socket) do
{:noreply,
socket
|> stream_insert(:trades, trade, at: 0)
|> stream_delete(:trades, -1)}
end
<ul id="trades" phx-update="stream">
<%= for {id, trade} <- @streams.trades do %>
<li id={id} class="flex justify-between text-sm">
<span><%= trade.price %></span>
<span><%= trade.qty %></span>
</li>
<% end %>
</ul>
Use Tailwind for visual flair:
- Green/red for price direction (
text-green-600
,text-red-600
) -
animate-pulse
to show price volatility -
overflow-y-auto h-60
to contain rapid updates
Resilient Data Layers with PubSub
Decouple WebSocket logic with a MarketDataServer
GenServer:
defmodule MarketDataServer do
use GenServer
def start_link(pair), do: GenServer.start_link(__MODULE__, pair)
def init(pair) do
WebSockex.start_link(..., self(), ...)
{:ok, %{pair: pair}}
end
def handle_info({:websocket, data}, state) do
Phoenix.PubSub.broadcast(MyApp.PubSub, "market:#{state.pair}", {:tick, data})
{:noreply, state}
end
end
Each LiveView subscribes only to the stream it cares about.
Initial Load: Historical Data
Pair live streaming with an HTTP seed on mount:
{:ok, resp} = Req.get("https://api.binance.com/api/v3/klines?symbol=BTCUSDT&interval=1m")
candles = parse_klines(resp.body)
{:ok, assign(socket, candles: candles)}
Render the chart server-side on first load. Then push new points from the WebSocket stream.
Filters and User Interactions
Let users toggle symbols or timeframes using LiveView’s phx-click
or phx-change
.
<select name="pair" phx-change="change_pair">
<option value="BTCUSDT">BTC</option>
<option value="ETHUSDT">ETH</option>
</select>
def handle_event("change_pair", %{"pair" => pair}, socket) do
# unsubscribe, subscribe to new pair, reset assigns
{:noreply, socket}
end
No page reload. No JS. Just LiveView.
Real-Time Alerts
Let users define thresholds. Track them in a process or with Oban
:
if price >= alert.threshold do
Oban.insert!(%MyApp.Jobs.SendNotification{user_id: alert.user_id})
end
In LiveView:
if alert_triggered do
assign(socket, alert_message: "BTC > $30k 🚀", alert_triggered: true)
end
Show it inline with:
<%= if @alert_triggered do %>
<div class="bg-yellow-100 p-4 rounded shadow"> <%= @alert_message %> </div>
<% end %>
Internal Tools: Dashboards & Monitoring
Use this same stack to build:
- Admin UIs for monitoring trade flow
- Fraud detection panels with live rule hits
- Payment system monitors showing queue depth
All real-time. All server-driven. All scalable.
Why LiveView Wins for Financial UIs
- ✅ WebSockets out of the box
- ✅ Clean server-state model
- ✅ Live updates via
handle_info
- ✅ Fast, minimal HTML updates
- ✅ No JS frameworks or client state needed
- ✅ Scales horizontally with Phoenix channels
Build experiences that feel native—but run in the browser.
Want to Go Pro?
Get the PDF:
Phoenix LiveView: The Pro’s Guide to Scalable Interfaces and UI Patterns
- Live dashboards
- Streaming data
- Tailwind-styled components
- WebSocket + REST integrations
- Patterns for async UX and alerts
Whether it’s crypto, equities, or internal ops — build it right. Build it live. Build it with Phoenix.