Was sind PocketBase Realtime Functions? Du tippst in einem Browserfenster eine Nachricht, und im zweiten Fenster erscheint sie im selben Moment. Ohne eigenen WebSocket-Server, ohne Polling, ohne Zusatzdienst. Genau das liefert dir PocketBase von Haus aus. Die Realtime-Funktionen gehören zu den Features, die Einsteiger am schnellsten begeistern, weil du mit sehr wenig Code ein sichtbares Ergebnis bekommst.
In diesem Beitrag lernst du, wie die PocketBase Realtime API funktioniert, wie du Subscriptions auf ganze Collections oder einzelne Records anlegst und wie du einen Live-Chat in rund 30 Zeilen baust.
Was steckt hinter PocketBase Realtime?
PocketBase ist ein Open-Source-Backend in einer einzigen Datei: Datenbank (SQLite), Authentifizierung, Dateiablage, Admin-Dashboard und eben Realtime. Für die Echtzeit-Funktionen setzt PocketBase nicht auf WebSockets, sondern auf Server-Sent Events (SSE). Das ist eine schlanke, HTTP-basierte Technik, bei der der Server Nachrichten über eine offen gehaltene Verbindung an den Client schickt.
Der Ablauf sieht so aus:
- Der Client öffnet eine SSE-Verbindung zu
GET /api/realtime. - Der Server antwortet mit einem
PB_CONNECT-Event und einer eindeutigenclientId. - Der Client teilt per
POST /api/realtimemit, welche Themen (Topics) er abonnieren möchte, zum Beispielmessages/*. - Sobald ein Record erstellt, geändert oder gelöscht wird, schickt PocketBase ein Event an alle passenden Abonnenten.
Die gute Nachricht: Um all das musst du dich nicht selbst kümmern. Das offizielle JavaScript-SDK erledigt Verbindungsaufbau, Abo-Verwaltung und sogar das automatische Wiederverbinden für dich.
Subscriptions: ganze Collection oder einzelner Record
PocketBase kennt zwei Arten von Abonnements. Du entscheidest je nach Anwendungsfall, wie fein du zuhören willst.
Subscription auf eine ganze Collection
Mit dem Platzhalter * bekommst du jedes Event, das irgendeinen Record der Collection betrifft. Ideal für Chats, Feeds, Aktivitätslisten oder Dashboards.
|
1 2 3 4 5 6 7 8 |
import PocketBase from 'pocketbase'; const pb = new PocketBase('http://127.0.0.1:8090'); pb.collection('messages').subscribe('*', (e) => { console.log(e.action); // "create", "update" oder "delete" console.log(e.record); // der betroffene Record }); |
Subscription auf einen einzelnen Record
Statt * übergibst du die ID eines Records. Dann hörst du nur auf Änderungen genau dieses Datensatzes. Das passt zum Beispiel für ein Bestellstatus-Tracking, eine Profilseite oder einen gemeinsamen Zähler.
|
1 2 3 |
pb.collection('orders').subscribe('RECORD_ID', (e) => { console.log('Neuer Status:', e.record.status); }); |
Abos wieder beenden
Offene Abonnements solltest du aufräumen, sobald du sie nicht mehr brauchst, etwa wenn eine Komponente in React oder Vue verschwindet. Dafür gibt es unsubscribe:
|
1 2 3 4 5 6 7 8 |
// nur ein bestimmtes Topic beenden pb.collection('orders').unsubscribe('RECORD_ID'); // alle Collection-Abos mit "*" beenden pb.collection('messages').unsubscribe('*'); // alle Abos dieser Collection beenden pb.collection('messages').unsubscribe(); |
Praktisch: subscribe() liefert ein Promise, das zu einer Unsubscribe-Funktion auflöst. Du kannst dir also auch einfach const stop = await pb.collection('messages').subscribe(...) merken und später stop() aufrufen.
Sicherheit: API-Regeln gelten auch für Realtime
Ein Punkt, den Einsteiger oft übersehen: Realtime-Events sind kein Hintertürchen. PocketBase prüft für jedes Event, ob der Abonnent den Record überhaupt sehen darf. Bei einer Subscription auf die ganze Collection entscheidet die List-Regel, bei einer Subscription auf einen einzelnen Record die View-Regel. Ist ein Nutzer eingeloggt, schickt das SDK sein Auth-Token automatisch mit, sodass Regeln wie @request.auth.id != "" greifen.
Für eine schnelle Demo kannst du die Regeln im Dashboard auf öffentlich stellen. In einer echten Anwendung solltest du sie aber bewusst einschränken.
Demo: Live-Chat in rund 30 Zeilen
Jetzt wird es spannend. Mit diesem Beispiel baust du einen funktionierenden Live-Chat, den du in zwei Browserfenstern nebeneinander testen kannst.
Schritt 1: PocketBase starten und Collection anlegen
- Lade PocketBase für dein Betriebssystem herunter und starte es mit
./pocketbase serve. - Öffne das Dashboard unter
http://127.0.0.1:8090/_/und lege einen Superuser an. - Erstelle eine Base-Collection
messagesmit den Textfeldernauthorundtext. Achte darauf, dass das Autodate-Feldcreatedvorhanden ist, damit du nach Zeit sortieren kannst. - Setze für die Demo die Regeln List, View und Create auf öffentlich (leeres Feld statt gesperrt).
Schritt 2: Die HTML-Datei
Speichere den folgenden Code als chat.html und öffne die Datei über einen lokalen Webserver, zum Beispiel mit npx serve.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
<ul id="chat"></ul> <form id="form"> <input id="name" placeholder="Dein Name" required> <input id="text" placeholder="Nachricht ..." autocomplete="off" required> <button>Senden</button> </form> <script type="module"> import PocketBase from 'https://cdn.jsdelivr.net/npm/pocketbase/dist/pocketbase.es.mjs'; const pb = new PocketBase('http://127.0.0.1:8090'); const chat = document.getElementById('chat'); const show = (msg) => { const li = document.createElement('li'); li.textContent = `${msg.author}: ${msg.text}`; chat.append(li); }; // 1. Bisherige Nachrichten laden const list = await pb.collection('messages').getList(1, 50, { sort: 'created' }); list.items.forEach(show); // 2. Live auf neue Nachrichten hören pb.collection('messages').subscribe('*', (e) => { if (e.action === 'create') show(e.record); }); // 3. Nachricht senden document.getElementById('form').addEventListener('submit', async (ev) => { ev.preventDefault(); const text = document.getElementById('text'); const author = document.getElementById('name').value; await pb.collection('messages').create({ author, text: text.value }); text.value = ''; }); </script> |
Öffne die Seite in zwei Fenstern, schreib in einem davon, und die Nachricht taucht sofort im anderen auf. Beachte: Die eigene Nachricht wird nicht doppelt eingefügt, weil sie nur über das Realtime-Event angezeigt wird, nicht direkt nach dem Senden.
Der eigentliche Realtime-Teil sind gerade einmal drei Zeilen. Alles andere ist ganz normales DOM-Handling.
Variante: Live-Dashboard mit derselben Technik
Dasselbe Prinzip trägt auch ein Dashboard. Angenommen, du hast eine Collection orders und willst live sehen, wie viele Bestellungen offen sind. Statt bei jedem Event alles neu zu laden, reagierst du gezielt auf die Aktion:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
let open = (await pb.collection('orders').getList(1, 1, { filter: 'status = "open"', })).totalItems; const render = () => { document.getElementById('open-count').textContent = open; }; render(); pb.collection('orders').subscribe('*', async () => { // einfach und robust: Zähler bei jeder Änderung neu abfragen open = (await pb.collection('orders').getList(1, 1, { filter: 'status = "open"', })).totalItems; render(); }); |
Für kleine bis mittlere Datenmengen ist dieses Muster völlig ausreichend und vor allem leicht verständlich. Wenn du später optimieren willst, kannst du anhand von e.action und e.record.status den Zähler auch direkt im Client hoch- oder runterzählen.
Praxistipps für Realtime mit PocketBase
- Erst laden, dann abonnieren: Realtime liefert nur Änderungen ab dem Zeitpunkt des Abos. Den Anfangszustand holst du dir wie im Chat-Beispiel per
getList. - Relationen mitliefern: Über die Optionen von
subscribe()kannst du zum Beispielexpandangeben, damit verknüpfte Records direkt im Event stecken. - Aufräumen nicht vergessen: Rufe in Single-Page-Apps beim Verlassen einer Ansicht
unsubscribe()auf, sonst sammeln sich doppelte Listener. - Node.js braucht ein Polyfill: Im Browser ist
EventSourceeingebaut. In Node.js oder React Native installierst du ein passendes EventSource-Polyfill. - Reverse Proxy prüfen: Läuft PocketBase hinter Nginx, darf der Proxy SSE-Antworten nicht puffern, sonst kommen Events verzögert an.
Fazit
Die eingebauten Realtime-Funktionen machen PocketBase zu einem idealen Einstieg in Echtzeit-Apps. Du brauchst keinen separaten WebSocket-Server, die API-Regeln schützen deine Daten automatisch, und mit subscribe('*') oder subscribe('RECORD_ID') hast du die Wahl zwischen breitem und gezieltem Zuhören. Probier den Live-Chat aus: Der Moment, in dem die Nachricht im zweiten Fenster aufpoppt, ist die beste Motivation für dein nächstes Projekt. Alle Details findest du in der offiziellen Dokumentation zur PocketBase Realtime API.
FAQ zu PocketBase Realtime
Nein. PocketBase verwendet Server-Sent Events (SSE). Der Server schickt Events über eine offene HTTP-Verbindung an den Client. Neue Abos oder Abmeldungen sendet der Client per normalem POST-Request. Jedes Event enthält eine Das regeln die API-Regeln der Collection. Für Collection-Abos mit Das JavaScript-SDK baut die Verbindung automatisch neu auf und registriert deine Subscriptions erneut. Events, die während der Unterbrechung passiert sind, werden allerdings nicht nachgeliefert. Lade bei Bedarf den aktuellen Stand neu. Ja. Neben dem JavaScript-SDK gibt es ein offizielles Dart-SDK mit derselben
Nutzt PocketBase WebSockets für Realtime?
Welche Events kann ich empfangen?
action mit dem Wert create, update oder delete sowie den betroffenen record.Wer darf welche Realtime-Events sehen?
* gilt die List-Regel, für Abos auf einen einzelnen Record die View-Regel.Was passiert, wenn die Verbindung abbricht?
Funktioniert Realtime auch mit Flutter oder Dart?
subscribe– und unsubscribe-Logik.
