---
id: 'realtime'
title: 'Realtime'
description: 'Send and receive messages to connected clients.'
subtitle: 'Send and receive messages to connected clients.'
hideToc: true
---
Supabase provides a globally distributed cluster of [Realtime](https://github.com/supabase/realtime) servers that enable the following functionality:
- [Broadcast](/docs/guides/realtime/broadcast): Send ephemeral messages from client to clients with low latency.
- [Presence](/docs/guides/realtime/presence): Track and synchronize shared state between clients.
- [Postgres Changes](/docs/guides/realtime/postgres-changes): Listen to Postgres database changes and send them to authorized clients.
### Realtime API
By default Realtime is disabled on your database. Let's turn on Realtime for a `todos` table.
1. Go to the [Database](https://supabase.com/dashboard/project/_/database/tables) page in the Dashboard.
2. Click on **Publications** in the sidebar.
3. Control which database events are sent by toggling **Insert**, **Update**, and **Delete**.
4. Control which tables broadcast changes by selecting **Source** and toggling each table.
```sql
alter
publication supabase_realtime add table todos;
```
From the client, we can listen to any new data that is inserted into the `todos` table:
```js
// Initialize the JS client
import { createClient } from '@supabase/supabase-js'
const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY)
// Create a function to handle inserts
const handleInserts = (payload) => {
console.log('Change received!', payload)
}
// Listen to inserts
supabase
.channel('todos')
.on('postgres_changes', { event: 'INSERT', schema: 'public', table: 'todos' }, handleInserts)
.subscribe()
```
```dart
import 'package:supabase_flutter/supabase_flutter.dart';
void main() async {
// Initialize the Flutter client
Supabase.initialize(
url: 'https://.supabase.co',
anonKey: '',
realtimeClientOptions: const RealtimeClientOptions(
eventsPerSecond: 2,
),
);
runApp(const MyApp());
}
final supabase = Supabase.instance.client;
void handleInserts(payload) {
print('Change received! $payload');
}
// Listen to inserts
supabase
.channel('todos')
.onPostgresChanges(
event: PostgresChangeEvent.insert,
schema: 'public',
table: 'todos',
callback: handleInserts)
.subscribe();
```
```swift
// Initialize the Swift client
import Supabase
let supabase = SupabaseClient(supabaseURL: SUPABASE_URL, supabaseKey: SUPABASE_ANON_KEY)
// Create channel
let channel = await supabase.realtime.channel("todos")
// Create the observations before subscribing
let insertions = await channel.postgresChanges(
InsertAction.self,
schema: "public",
table: "todos"
)
await channel.subscribe()
for await insertion in insertions {
let todo = try insertion.decoded(as: Todo.self)
print("Todo inserted", todo)
}
```
Use [subscribe()](/docs/reference/javascript/subscribe) to listen to database changes.
The Realtime API works through PostgreSQL's replication functionality. Postgres sends database changes to a [publication](/docs/guides/database/replication#publications)
called `supabase_realtime`, and by managing this publication you can control which data is broadcast.
## Examples