Skip to content

Realtime event transport

Use a Realtime channel when backend producers need to send live events to a browser dashboard, admin console, or operations view. The route receives events, normalizes the payload, and broadcasts it through a named channel.

Terminal window
import { backend } from "@layeron/core"
import { realtime } from "@layeron/modules"
const app = backend()
const live = realtime({
name: "transport",
historyLimit: 500,
})
app.use(live)
Terminal window
app.post("/feeds/:feedId/events", async (request) => {
const pathSegments = new URL(request.url).pathname.split("/")
const feedId = pathSegments[2]
const body = await request.json()
const channel = live.channel(`feed_${feedId}`)
return await channel.broadcast({
type: body.type,
data: {
feedId: feedId,
eventId: body.eventId,
payload: body.payload,
receivedAt: new Date().toISOString(),
},
metadata: {
source: body.source ?? "api",
},
idempotencyKey: body.eventId,
})
})

Use an idempotencyKey when the producer may retry the same event. Realtime keeps the event stream stable while still allowing safe producer retries.

Terminal window
app.get("/feeds/:feedId/events", async (request) => {
const pathSegments = new URL(request.url).pathname.split("/")
const feedId = pathSegments[2]
return await live.channel(`feed_${feedId}`).history({
limit: Number(new URL(request.url).searchParams.get("limit") ?? 100),
cursor: new URL(request.url).searchParams.get("cursor") ?? undefined,
})
})

The dashboard can call this route after reconnecting and continue from the cursor returned by the previous page.

Use a second event type for commands that should travel over the same live stream:

Terminal window
app.post("/feeds/:feedId/control", async (request) => {
const pathSegments = new URL(request.url).pathname.split("/")
const feedId = pathSegments[2]
const body = await request.json()
return await live.channel(`feed_${feedId}`).publish({
type: "feed.control",
data: {
action: body.action,
target: body.target,
requestedAt: new Date().toISOString(),
},
idempotencyKey: body.commandId,
})
})

Use channels for fan-out event transport. Use rooms when the same stream also needs membership, presence, room metadata, or collaborative state.