Realtime Egress FAQ #48391
Realtime Egress FAQ
#48391
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
This is a copy of a troubleshooting article on Supabase's docs site. It may be missing some details from the original. View the original article.
Realtime Egress is billed as part of your project's unified egress usage. This FAQ walks through what's counted, what isn't, and how to investigate a gap between the two.
What exactly is included in the Realtime Egress metric?
Realtime Egress measures data sent from the Realtime server to a connected client over an open WebSocket connection, plus any request made to the HTTP Broadcast endpoint. This includes Broadcast messages, Postgres Changes payloads, Presence events, and Phoenix protocol frames sent over the same socket (see below).
It does not include internal traffic between the Realtime server and your Postgres database (logical replication,
pgoutputreads for Broadcast from Database, or replication slot management). That traffic never reaches a client and isn't part of this metric.Does it include only bytes delivered to connected clients, or also internal DB → Realtime replication traffic?
Only data the server sends to the WebSocket, and any HTTP Broadcast request. DB → Realtime logical replication traffic (the connection Realtime uses internally to read changes for Broadcast from Database or Postgres Changes) is not counted — it never leaves the Realtime service to reach a client, so it isn't part of Egress.
Does it include replication slot initialization/recreation or Broadcast from database cold-start traffic?
No. Replication slot creation, checks, and reconnection attempts to your database are internal to the Realtime service and Postgres. Even if your tenant is frequently idling out and starting back up (for example, logs showing
Stop tenant ... because of no connected usersfollowed by slot recreation), that activity is not what's reflected in your billed Realtime Egress.Does it include Phoenix/WebSocket protocol overhead (handshake, heartbeat, phx_join, phx_leave, rejoin frames)?
Yes — any message the server sends over an open socket counts, including heartbeats and Phoenix control frames (
phx_reply,phx_close, rejoin payloads). In practice this overhead is minimal compared to actual application data, unless a client is stuck in a join/leave loop (for example, a broken reconnect handler that repeatedly subscribes and unsubscribes from the same channel). Realtime tracks join rate internally, so a runaway rejoin loop is something worth ruling out if your numbers look unusually high relative to your connection count.Can repeated tenant stop/start or cold-start cycles cause large billed egress even when payload is small?
No. Tenant idling out (
no connected users) and starting back up on the next connection is a normal part of the multi-tenant architecture and is not a mechanism that inflates Realtime Egress. If you're seeing a large gap between your application-measured payload and your billed egress, look at message volume and fan-out first (see below) rather than tenant lifecycle events.Is the dashboard graph batched or attributed in a way that could make one day look much higher than actual usage?
No known issue causes this. The daily Realtime Egress figure reflects real usage attributed to that day, not an artifact of how the graph is rendered or rolled up.
Is a breakdown of Realtime Egress available by source or type (Broadcast / Postgres Changes / Presence / protocol overhead)?
Not currently. Realtime Egress is reported as a single aggregate number — there's no per-source or per-event-type breakdown available in the dashboard or usage APIs today.
Measured message payload is tiny — why is billed Realtime Egress so much higher?
This is the most common source of confusion, and almost always comes down to counting writes instead of counting delivered events. A few things to check before assuming a billing issue:
INSERT,UPDATE, andDELETEsubscriptions, or multiple overlappingpostgres_changesfilters), the same underlying row change can be delivered multiple times to the same client.REPLICA IDENTITY FULL), which can be several kilobytes even for a small logical change — especially with wide tables or TOASTed columns. You can reduce this by filtering which changes are sent so irrelevant rows are never delivered, and by selecting specific columns to shrink the payload of the rows that are.Before escalating a gap between measured payload and billed egress, re-derive your estimate using delivered events, not writes:
(events per day) × (average delivered payload size) × (average concurrent subscribers). This calculation frequently accounts for a gap that initially looks inexplicable. The Realtime observability report can help here — it shows number of connected clients, payload size, and rate of joins for your project.What should be checked before contacting Supabase support about a Realtime Egress discrepancy?
postgres_changessubscriptions that could cause duplicate delivery.phx_join/phx_leavecycles) as a source of excess protocol overhead.Related guides
All reactions