Skip to main content
FlowFn
IntegrationsTemplatesPricingDocsBlogSign inStart free
All posts
StreamsRealtimeGamesTutorial

Build a Realtime Multiplayer App with FlowFn Streams — No WebSocket Server to Run

Define a few named channels, open a WebSocket from your game, and you have live rooms with presence, an AI host that answers the room with zero server code, and a leaderboard that updates in real time — all without standing up (or scaling) a socket server.

FlowFn Team · Product

15 Jul 2026 · 7 min read

Realtime is the part of multiplayer that eats weekends: a WebSocket server, presence tracking, fan-out across instances, reconnection, rate limits, auth. FlowFn Streams gives you all of that as a managed surface. You define a stream in the dashboard — a set of named channels — and clients connect to a hosted gateway, join rooms, and publish/subscribe. Fan-out and presence ride Redis, so any number of gateway boxes serve any socket; you never touch the plumbing.

The twist that makes it more than "hosted sockets": a channel can carry a binding — publishing a message can run a workflow, call your stream's own server code, ask a streaming agent, or have your AI answer the room. To make it concrete, we'll build Trivia Live: a multiplayer trivia game where players buzz in answers, an AI host judges them, and a live leaderboard updates in real time.

Here's the payoff — the live view of the running game, across all gateway instances:

The Logs tab: live rooms, usage, and the realtime activity feed

Three rooms live right now, a usage chart, and an activity feed showing the trivia session as it happens — players connecting, joining room-42, and each binding firing (answers, score). Let's build it.


Step 1 — Create a stream

Streams are an App-owned artifact. From Streams, hit New stream: name it, pick the App, and it seeds three starter channels you can edit any time.

The New stream drawer

Note Open identity — leave it off and players must present a signed token (launch mode); flip it on for token-free prototyping. We'll come back to that.


Step 2 — Design your channels

A stream is really just named channels — typed pipes for kinds of messages — and each channel's authority controls who may publish to it.

The Channels tab: named channels with authority and binding badges

For Trivia Live:

  • answers (Players) — players buzz in their answer. Bound to Call AI (more below).
  • host (FlowFn only) — the AI host's verdicts. FlowFn-only means no socket can publish here, so players can't impersonate the host — only the engine writes it.
  • score (Players) — a correct/incorrect signal, bound to a stream function.
  • scores (FlowFn only) — the live leaderboard, pushed by stream code.
  • chat (Players) — lobby banter.

Everyone in a room receives every channel; authority only gates publishing. The three authorities are Players (players + your game server), Server only (server key only — for authoritative state clients can't forge), and FlowFn only (engine output — bindings and stream code).


Step 3 — Connect a client

The Connection tab is your integration guide: the WebSocket URL, your secret server key, and player-token minting.

The Connection tab: WebSocket URL, server key, tokens, and a client snippet

The model is simple and safe:

  • Your game server holds the server key (full authority — keep it server-side) and mints a short‑lived signed player token per user via POST /stream/v1/tokens.
  • The client connects with that token, joins a room, and publishes:
const ws = new WebSocket('wss://engine.flowfn.com/stream/v1?stream=strm-triv1a9f&token=PLAYER_TOKEN');
ws.onmessage = (e) => console.log(JSON.parse(e.data));   // welcome, ack, peer_joined, message…
ws.onopen = () => {
  ws.send(JSON.stringify({ op: 'join',    room: 'room-42' }));
  ws.send(JSON.stringify({ op: 'publish', room: 'room-42', channel: 'answers', payload: { text: 'Paris' } }));
};

Everyone in room-42 receives that message, and presence is automatic — a peer_joined frame and a member list arrive on join, no extra calls. (First-party Godot/Unity SDKs wrap all of this.)


Step 4 — Make a message do something (bindings)

This is where Streams stops being a dumb pipe. Click the ⚡ on a channel and you can bind it: every player message on that channel fires FlowFn work.

The channel binding dialog: the Call AI binding

There are four kinds:

Binding What a message triggers
Run a workflow a workflow run (e.g. record the match result)
Run a stream function a function you wrote on the Code tab (synchronous)
Ask a streaming agent a streaming agent that remembers the room
Call AI your team's AI answers the room — no server code

We bind answers to Call AI with a host persona ("decide if the answer is correct and reply with a short, fun verdict"), reply on the host channel, cap the reply, and set a 2‑second cooldown (each call spends real AI credits). Now every buzz-in runs one AI completion and publishes the verdict back into the room — a live AI game host with zero backend code. And because engine-side replies never re-fire bindings, there's no loop to worry about.


Step 5 — Write the backend (stream code)

When you need real logic — scoring, a leaderboard — the Code tab is a sandboxed backend that runs on FlowFn, no server to deploy. A function binding runs one of your exports per message.

The Code tab: a tallyScore function using ctx.sheets and ctx.streams.publish

Our tallyScore bumps the player's points in a Data Sheet and pushes the fresh top‑5 to everyone:

exports.tallyScore = async (msg, ctx) => {
  const { room, payload } = msg;              // { player, correct }
  if (payload.correct) {
    const row = await ctx.sheets().getRow('scores', payload.player);
    await ctx.sheets().updateRow('scores', payload.player, { points: (row?.points ?? 0) + 10 });
  }
  const board = await ctx.sheets().query('scores', { sort: '-points', limit: 5 });
  await ctx.streams.publish(room, 'scores', { leaderboard: board });   // → the FlowFn-only channel
};

ctx is the whole toolbox — ctx.streams.publish (reply into a room), ctx.sheets (the linked database), ctx.ai.call (the same AI as the binding), ctx.http (SSRF‑guarded fetch), ctx.workflows.run / ctx.agents.run (allow‑listed), and ctx.env. It runs in an isolated sandbox — no require, no raw network — with a Generate with AI button and a cheat sheet for the full API.


Step 6 — Pick the AI and link data (Tools)

One place sets the stream's AI and its database: the Tools tab.

The Tools tab: the stream's AI model and linked database

The AI here is what both the Call‑AI binding and ctx.ai.call use — a model on the platform key, or your own via a team connection (BYOK) with a fallback. Data Sheets links a database so ctx.sheets() needs no id. And Workflows / Agents are deny-by-default allow-lists — stream code may only invoke the ids you list here, so a hot game loop can't reach across your whole workspace.


Step 7 — Watch it run

Back to that hero shot — the Logs tab is your live window (that top image). The Live panel shows every room and connection right now, across all gateway instances; Usage tracks messages/day and peak concurrency; and the activity feed logs every connect, join, and binding — including your stream functions' console.log. It's also the first place to look when a binding doesn't fire: if the feed shows only connect/join and no binding_* row, the channel you published to has no binding.


The whole picture

Piece What it gives you
Channels Named pipes + authority (who may publish)
Connection Hosted WebSocket, server key, signed player tokens
Rooms Ephemeral, presence built in, reaped when idle
Bindings A message → workflow / function / agent / AI
Code Sandboxed ctx.* backend, no server to run
Tools The stream's AI + linked database + allow-lists
Logs Live rooms/connections + usage + activity feed

Scaling, presence, fan-out, reconnection, rate limits, and auth are all handled — gateway boxes are stateless behind Redis, so it grows without you.


Wrap-up

Streams collapse the hardest part of multiplayer — the realtime server — into a design-time object. Define channels, connect a client, and you have live rooms with presence. Add a binding and a message can run a workflow, your code, an agent, or your AI, right in the room. It's the connective tissue for the rest of FlowFn: the agent that hosts the game, the workflow that records the match, the Data Sheet that holds the scores — all reachable from a socket message.

Start with two channels and the connect snippet, watch the activity feed light up as you join a room, then bind a channel to Call AI and let the room talk to your AI. Build a room, join it, and watch it go live.

Read next

Tutorial
Getting-Started
No-Code

Build a Complete App in a Weekend with FlowFn

Six tutorials, six features — a database, a hosted site, a form, a workflow, a dashboard, an AI agent, and an MCP server. On their own they're building blocks. Put them together and they're a real, running business app. This is the capstone: we take everything from the series and assemble the whole Bloom & Bean café — front to back, no servers, no database ops, no deploy — in a single weekend.

FlowFn Team · 15 Jul 2026 · 6 min read

MCP
AI
Integrations

Give AI Clients a Safe Toolset: Host an MCP Server with FlowFn

Your app already knows how to look up an order, run a workflow, and answer a question. What if Claude Desktop, Cursor, or any MCP-capable assistant could call those abilities directly — but only the ones you allow, behind a token you can rotate, billed to you? FlowFn's MCP feature turns any App into a hosted Model Context Protocol server: attach the workflows, agents, data sheets, and tools you want to expose, hand out a bearer token, and an external AI can use your app as a toolset.

FlowFn Team · 15 Jul 2026 · 7 min read

Visualizers
Dashboards
Charts

Build a Live Dashboard with FlowFn Visualizers — No SQL, No BI Tool

You've got data flowing through your app — orders, signups, sensor readings, run outcomes. Turning it into a dashboard usually means a BI tool, a warehouse connection, and someone who speaks SQL. FlowFn Visualizers skips all of that: define a few typed fields, drop in the chart types you want, and point a workflow at it. You get a public, embeddable, auto-refreshing dashboard with real charts — and zero query language.

FlowFn Team · 15 Jul 2026 · 7 min read

Build your first workflow today

Start free — connect your apps, add AI, and ship an automation you can actually maintain. No credit card required.

Get started free