Skip to content
Appwrite Realtime

Everything in Appwrite is realtime_

Rows, files, function executions, sessions, teams, and presence all emit events on the same WebSocket. Subscribe once, get changes in milliseconds instead of polling, and only ever receive what the user can read.

Appwrite events

  • Databasesrows
  • Storagefiles
  • Functionsexecutions
  • Authaccount
  • Presencepresences

Realtime

1 WebSocket
Web app
Mobile app
Dashboard
Not just databases
Every service
Shared by all subscriptions
1 socket
From write to subscriber
Milliseconds
Filtered server-side
Queries
Live online status
Presence

One connection, many subscriptions

Create a Realtime client once and every subscription shares a single WebSocket. Add one with subscribe(), swap its channels or queries with update(), and drop it with unsubscribe(), all without reconnecting.

rowsfilespresences

Realtime client

1 WebSocket

Every service publishes to a channel

Databases, Storage, Functions, Auth, teams, and presence all stream on the same socket. The Channel helper builds the string with a fluent API, so leave an ID blank for a wildcard or append .create() to narrow the stream.

Databases

  • Channel.tablesdb('main').table('orders').row()

    tablesdb.<ID>.tables.<ID>.rows

  • Channel.tablesdb('main').table('orders').row('8f2a')

    tablesdb.<ID>.tables.<ID>.rows.<ID>

  • Channel.rows()

    rows

Storage

  • Channel.bucket('media').file()

    buckets.<ID>.files

  • Channel.bucket('media').file('invoice')

    buckets.<ID>.files.<ID>

  • Channel.files()

    files

Functions

  • Channel.executions()

    executions

  • Channel.function('checkout')

    functions.<ID>

  • Channel.executions().create()

    executions.create

Auth, teams, and presence

  • Channel.account()

    account

  • Channel.teams()

    teams.*

  • Channel.presences()

    presences

Filter events before they reach you

Pass queries when you subscribe and Appwrite filters events on the server, so your callback only runs for updates that match. The methods are the ones you already use for lists, from equal to isNull and or.

Events on the channel

  • person: 'paige'match
  • person: 'walter'dropped
  • person: 'paige'match

Filtered on the server

[Query.equal('person', ['paige'])]

Presence that is durable and live

A presence record carries a user, a free-form status, optional metadata, and an expiry. List presences to see who is here, and subscribe for upsert, update, and delete events in milliseconds.

Who is here

presences
  • PApaige@example.comediting
  • WAwalter@example.comonline
  • HAhappy@example.comaway

expiresAt

Slides on heartbeat

A predictable payload on every event

Every message carries the events that triggered it, the channels that can receive it, a server timestamp, and a payload matching the resource response model. Branch on the event names, then apply the payload.

Every message carries

eventsstring[]

['tablesdb.main.tables.orders.rows.8f2a.update']

channelsstring[]

['rows', 'tablesdb.main.tables.orders.rows']

payloadobject

{ $id: '8f2a', status: 'paid' }

Permission-aware subscriptions

Subscriptions use the same permissions as the rest of Appwrite, so a user only receives updates for resources they can read. Realtime uses the session you had when you subscribed, so reconnect when it changes.

Row updated

Permission.read(Role.team('acme'))

paige@example.com
Event delivered
toby@example.com
Nothing delivered

Tools built for developers and agents_

API-first by design. Use the Console, Realtime, SDKs, CLI, Terraform, MCP, and agent skills on the same project.

FAQ_

Realtime is a third protocol for talking to Appwrite, alongside REST and GraphQL. Instead of requesting new data over HTTP, you subscribe once and the server pushes new data to every connected client over a WebSocket as soon as it changes. Subscriptions cover events from all of Appwrite services, not just databases.

Client SDKs use a single WebSocket per Realtime client for all subscriptions. Adding one with subscribe(), replacing its channels or queries with update(), and dropping it with unsubscribe() all apply on the existing socket where supported, so there is no full reconnect. The connection closes when you call realtime.disconnect().

Every service publishes channels: account and sessions, teams and memberships, rows, files, function executions, and presences. The Channel helper class builds the channel string for you with a fluent API, so you can target one row or every row in a table. Leave an ID blank to subscribe with a wildcard, and append .create(), .update(), or .delete() to narrow the stream to a single event type.

Yes. Pass queries as a third parameter when you subscribe and Appwrite filters events server-side, so your callback only runs for updates that match. Realtime supports Query.equal, Query.notEqual, the greater than and less than comparisons, Query.isNull, Query.isNotNull, Query.and, and Query.or.

Every message carries four properties: events (the Appwrite events that triggered the update), channels (the channels that can receive it), timestamp (an ISO 8601 time in UTC from the server), and payload (the same data as the matching response model). Branch on the event names in events to decide how to update your UI.

No. Every subscription is secured by the same permissions system used by rows, files, and presences, so a user only receives updates for resources they have permission to access. Granting read to Role.any() is what makes a resource stream to any client, including visitors who are not signed in.

Realtime authenticates with the session that existed when the subscription was created. If you authenticate after subscribing, that subscription will not receive updates for the new user, so create the session first. When a user signs out and another signs in, call realtime.disconnect() and subscribe again for the new session.

A presence is a short-lived record tied to a user, with a userId, a free-form status, optional metadata, and an expiresAt timestamp. It is durable, so you can list presences at any time, and live, so every change fires upsert, update, and delete events. Keep a record alive with a heartbeat, or use realtime.upsertPresence() so it is removed when the connection closes.

Not today. Realtime subscriptions are a client SDK feature and are not offered for Server SDKs with an API key. Presence records are the exception: they are also a regular HTTP resource, so server code can write them with an API key that has the presences.write scope and clients will see the change live.

Yes. The SDK derives the Realtime endpoint from your Appwrite endpoint, which is wss://<REGION>.cloud.appwrite.io/v1/realtime by default. If you run Appwrite behind a custom proxy and moved the Realtime route, call setEndpointRealtime on the client with your own value.

Start building with Realtime_

Subscribe to your first channel and watch rows, files, executions, and presence updates arrive as they happen.