Der Open-Source-Apply-Client für Schema-Datenbanken. Führen Sie ihn auf jedem Rechner aus, der Ihr eigenes PostgreSQL erreichen kann, koppeln Sie ihn einmal, und er hält diese Datenbank mit Ihren Enrichments konvergent – indem er aus einem Snapshot bootstrappt und anschließend einen Live-Delta-Feed über einen einzigen ausgehenden WebSocket anwendet. Ihr Connection String verlässt diesen Rechner nie.
Jede Anweisung ist revisionsgeschützt, sodass ein erneut ausgelieferter Batch zu denselben Zeilen konvergiert. Ein SQL-Fehler setzt den Batch zurück und stoppt — ein fehlerhaftes Delta wird niemals stillschweigend übersprungen.
Der Client zieht Zustand, keine Operationen: Jedes Delta trägt die vollständige(n) aktuelle(n) Zeile(n) einer geänderten Entity als idempotentes INSERT … ON CONFLICT … DO UPDATE, sodass das Ziel selbst dann konvergiert, wenn ein Batch verpasst wurde.
Database Syncs können auf verschiedene Weise genutzt werden – n8n, Make.com, MCP, rohe Webhooks oder den REST-Delta-Feed. Der Sync-Client ist der vollautomatische Weg: am wenigsten zu bauen und am wenigsten anfällig für Datenlecks.
Kein n8n-Szenario, kein Cron, kein Glue-Code. Einmal koppeln, und es startet aus dem Snapshot und wendet dann jedes Delta an, sobald es eintrifft.
Der Verbindungsstring wird über die Kommandozeile übergeben oder lokal im Modus 600 gespeichert — er wird niemals an Entity Enricher gesendet. Der Client verbindet sich ausschließlich nach außen.
Jedes Delta ist ein idempotenter, revisionsgeschützter Upsert. Stirbt der Client mitten im Batch, wird der Batch nach Ablauf seiner Lease erneut ausgeliefert, und ein erneutes Anwenden konvergiert zu denselben Zeilen.
Ein SQL-Fehler setzt den Batch zurück und meldet das fehlerhafte Delta. Der Server stellt den gesamten Batch dieser Anreicherung unter Quarantäne und schiebt die Warteschlange ohne ihn erneut nach, sodass der Client verbunden bleibt und weiter anwendet — eine fehlerhafte Zeile kann nicht alles Nachfolgende blockieren, und die unter Quarantäne gestellte Arbeit bleibt aufgelistet, bis Sie sich darum kümmern.
Registrieren Sie zunächst eine Datenbank für ein Schema, koppeln Sie dann einen Client und führen Sie ihn auf einem Rechner aus, der Ihre Datenbank erreichen kann.
Registrieren Sie auf der Seite Database Sync eine Datenbank für das Schema, das Sie spiegeln möchten, und prüfen Sie deren Datenbankschlüssel. Siehe Database Sync für das vollständige Modell. Dieser Schritt legt den Zieldialekt fest, den der Client anwendet.
Fügen Sie dies in ein Terminal ein. Das Skript überprüft eine cosign-Signatur vor der Installation.
curl -fsSL https://entityenricher.ai/install-eedatabase.sh | sh
Windows: iwr -useb https://entityenricher.ai/install-eedatabase.ps1 | iex. Oder laden Sie eine signierte Binärdatei aus den Releases herunter oder erstellen Sie sie aus dem Quellcode (Go ≥ 1.23): go build -o ee-database .
Quellcode und signierte Releases finden Sie unter TOT-Concept/ee-database (MIT).
Führen Sie ee-database pair aus. Ein Browser-Tab öffnet sich unter /database/connect mit einem Kurzcode — bestätigen Sie ihn und wählen Sie, welche Datenbank dieser Client synchronisieren soll.
ee-database pair --server https://entityenricher.ai Open this URL in your browser to confirm pairing: https://entityenricher.ai/database/connect?code=7QX-KP2 Code: 7QX-KP2 Waiting for confirmation...
Lieber ein Token? Erstellen Sie eines auf der Seite Database Sync (Sync-Client → Client koppeln) und übergeben Sie es direkt: ee-database pair --server … <refresh-token>.
Beim ersten Lauf ruft der Client den .sql-Snapshot ab und wendet ihn an, verbindet sich dann und streamt Deltas. --save-dsn speichert die Verbindungszeichenfolge lokal, sodass spätere Läufe keine Argumente benötigen.
Jeder Lauf prüft außerdem selbst die Provisionierungsrechte des Logins (Datenbank erstellen, DDL, DML) und meldet das Ergebnis an die Sync-Client-Karte, sodass eine fehlende Berechtigung sichtbar wird, bevor Deltas nicht angewendet werden können. Ist noch kein verknüpftes Schema veröffentlicht, bleibt der Client verbunden und wartet – die erste Veröffentlichung startet den Feed von selbst, ein Neustart ist nicht nötig.
ee-database run --dsn "postgres://user:pass@localhost:5432/mydb" --save-dsn
„Next to“ bedeutet netzwerknah, nicht auf dem Datenbankserver: jede Maschine oder jeder Container, der die DSN erreichen kann, funktioniert — einschließlich cloud-verwaltetem PostgreSQL (Azure, OVHcloud, AWS RDS…), das üblicherweise TLS erzwingt: …/mydb?sslmode=require.
Mehrere Datenbanken auf einer Maschine? Ein Sync-Host hebt die Kopplung eine Ebene höher: Koppeln Sie die Maschine einmal, und jede Datenbanksynchronisierung, die Sie ihr zuweisen, wird automatisch übernommen, bereitgestellt und synchron gehalten – für die Registrierung einer neuen Synchronisierung ist nie wieder eine Terminal-Sitzung nötig. Erfordert Client 1.5.0 oder neuer, der einmal pro Server statt einmal pro Maschine koppelt – so kann ein Host mehrere Entity Enricher-Instanzen nebeneinander bedienen.
Klicken Sie auf der Seite Database Sync auf die Symbolleisten-Schaltfläche Sync hosts und fügen Sie einen Host hinzu, der nach der Maschine benannt ist. Ein einmaliges Pairing-Token wird genau einmal angezeigt — eingebettet in einen host pair-Befehl zum Kopieren und Einfügen, mit geführten Einrichtungsschritten.
Führen Sie den Befehl auf dem Rechner aus, der Ihren Datenbankserver erreichen kann. Der --dsn ist eine Basis-Verbindungszeichenfolge, die den Server benennt, ohne Datenbanknamen — jeder zugewiesene Sync leitet daraus seine eigene Datenbank ab. Wie jeder DSN wird er lokal im Modus 600 gespeichert und niemals an Entity Enricher gesendet.
ee-database host pair --server https://entityenricher.ai \ --dsn "postgres://user:pass@host:5432/" <token>
Die Kopplung prüft selbst die Provisionierungsrechte des Logins (Datenbank erstellen, DDL, DML) und schlägt bei einer fehlenden Berechtigung sofort fehl. Bevorzugen Sie einen Login mit minimalen Rechten? Fügen Sie --admin-dsn hinzu, und die Provisionierung erstellt stattdessen jede fehlende Rolle und Datenbank über die Admin-Verbindung – der Admin-DSN wird nur zur Provisionierungszeit verwendet, niemals gespeichert.
ee-database host run
Der Host hält einen Control-Plane-WebSocket und reagiert auf Zuweisungen, die über die Oberfläche vorgenommen werden: Wählen Sie den Host bei der Registrierung einer Datenbank oder später im Tab Übersicht der Datenbank. Jeder zugewiesene Sync wird beansprucht, seine Datenbank bei Bedarf erstellt (in snake_case aus dem Namen des Syncs; pro Sync über database_names in der config.json des Hosts überschreibbar) und anschließend durch die unten beschriebene reguläre Schleife synchronisiert.
Eine Datenbank, die bereits mit einem anderen Client gekoppelt ist, wird gemeldet und übersprungen – niemals übernommen. Das Widerrufen des Hosts in der UI trennt den Rechner sofort ab, einschließlich aller pro Datenbank beanspruchten Zugangsdaten; Zuweisungen und bereits synchronisierte Daten bleiben erhalten, sodass ein erneut gekoppelter Host dort fortfährt, wo der alte aufgehört hat.
Deltas verlassen Entity Enricher über eine strikte FIFO-Outbox pro Datenbank. Der Server least das sichtbare Fenster für 120 Sekunden und pusht es als einen Batch; der Client wendet den gesamten Batch in einer einzigen Transaktion an und antwortet mit ack , was den Cursor vorrückt und sofort das nächste Fenster auslöst. Ein Client, der mitten im Batch ausfällt, ist durch den Ablauf des Lease und einen erneuten Push seitens des Servers abgedeckt — nichts geht verloren und nichts wird doppelt committet.
Bootstrap und Steady-State nutzen denselben Codepfad. Überspringen Sie den Bootstrap mit --skip-bootstrap, wenn Ihre Datenbank bereits befüllt ist.
Jede Anweisung trägt eine _sync_revision, sodass eine ältere Zeile niemals eine neuere überschreibt, auch nicht bei falscher Reihenfolge.
Ein SQL-Fehler setzt den Batch zurück und meldet das fehlerhafte Delta samt der gesamten beanstandeten Anweisung. Der Server stellt den Batch dieser Anreicherung unter Quarantäne und schiebt die Warteschlange ohne ihn erneut nach — der Client wendet den Rest weiter an. Nur ein Fehler, der kein Delta benennt, führt zu einem Exit-Code ungleich null.
Jedes angewendete Fenster meldet pro Tabelle die geschriebene Struktur – so braucht die Dimensionierung einer nächtlichen Neuanreicherung nie Log-Archäologie an Deltas, die bereits bestätigt und verschwunden sind.
applying 12 delta(s) (10831 .. 10842) in one transaction applied 12 delta(s) in 84ms — 38 statement(s): mushroom 4 upserts, mushroom_common_names 12 upserts + 4 prunes, mushroom_human_uses 14 upserts + 4 prunes acked up to delta 10842
Ein upsert entspricht einer Zeile, die Zähler sind also Zeilenanzahlen; ein prune ist das einzelne revisionsgesicherte DELETE, das die Kind- oder Verknüpfungszeilen entfernt, die eine neue Payload nicht mehr beansprucht. Kindzeilen werden an Ort und Stelle abgeglichen – niemals gelöscht und neu eingefügt. Mit --verbose erhalten Sie eine Zeile pro Delta, mit Entitätstyp, Laufzeit und eigener Struktur.
Der Zieldialekt wird durch die Registrierung der Schema-Datenbank in Entity Enricher festgelegt – der Client wendet genau das SQL an, das der Server erzeugt. PostgreSQL ist der Start-Dialekt; Renderer für MySQL / MariaDB, SQL Server und Oracle sind geplant (der MySQL-Treiber ist bereits enthalten). Die Ausführung mehrerer Anweisungen erfolgt treiberabhängig (pgx Simple Protocol, MySQL multiStatements).
Sofern die Zieldatenbank bereits existiert, benötigt der Login lediglich CONNECT für die Datenbank sowie USAGE + CREATE für das Zielschema. (Seit PostgreSQL 15 gewährt public nicht mehr standardmäßig allen CREATE.)
Alles Weitere folgt aus der Eigentümerschaft: Der Client legt die Replikattabellen selbst an, besitzt sie also, und Eigentümerschaft impliziert die Lese- und Schreibrechte, die die Daten-Deltas benötigen. Eigentümerschaft ist nicht optional — der Feed liefert auch Migrationsanweisungen (ALTER TABLE …, CREATE INDEX …), die PostgreSQL auf den Tabelleneigentümer beschränkt, und keine Kombination von Grants ersetzt sie.
Existieren die Replik-Tabellen bereits unter einem anderen Eigentümer, besteht die Rechteprüfung des Laufs zwar weiterhin — der Login kann neue Tabellen anlegen —, aber das erste Migrations-Delta schlägt fehl. Übertragen Sie sie mit ALTER TABLE … OWNER TO <login> (oder nehmen Sie den Login in die besitzende Rolle auf), statt Rechte zu ergänzen.
Eine Anweisung, die Ihre Datenbank ablehnt — meist wegen eines bereits vorhandenen Duplikats unter einem neuen Unique-Index —, stoppt den Feed nicht. Der Batch wird zurückgesetzt, der Client meldet das fehlerhafte Delta zusammen mit der gesamten beanstandeten Anweisung (nie gekürzt), und der Server stellt den Batch dieser Anreicherung unter Quarantäne und schiebt die Warteschlange ohne ihn erneut nach. Ihr Client wendet alles Folgende weiter an.
Vorgänge in Quarantäne bleiben im Tab Quarantäne der Seite Database Sync aufgeführt, bis Sie sich darum kümmern: Beheben Sie die Ursache in Ihrer Datenbank und injizieren Sie erneut – dabei wird die Entität aus ihrem aktuellen Zustand neu projiziert, statt die veraltete Anweisung zu wiederholen – oder verwerfen Sie den Vorgang, wenn die Zeile keine Rolle mehr spielt.
Ein fehlgeschlagener Bootstrap ist ein anderer Fall: Der Snapshot ist eine einzige Transaktion, es wird also nichts teilweise angewendet, und der Client speichert ihn im Profilverzeichnis der Kopplung als snapshot-failed.sql (Modus 0600, bei jedem Versuch ersetzt, beim nächsten Erfolg entfernt), damit Sie ihn mit psql -f prüfen oder erneut ausführen können.
Der Client initiiert den WebSocket über :443/wss. Ihr Datenbank-Host akzeptiert niemals eingehende Verbindungen — keine Ports zu öffnen, kein Ingress zu konfigurieren.
Eine Zugangsberechtigung ist an einen einzelnen Database Sync gebunden. Ein erneutes Pairing rotiert sie und trennt sofort die vorherige aktive Verbindung.
Das 365-Tage-Refresh-Token (im Modus 600 gespeichert) wird gegen 15-minütige Zugriffstoken eingetauscht, die den WebSocket authentifizieren. Ein Widerruf in der Benutzeroberfläche trennt einen aktiven Client innerhalb von ~1 Sekunde.
Ein verwalteter Host wird über einen kurzen eeh_…-Schlüssel gekoppelt statt über ein JWT: Der Server speichert nur dessen Hash, der Schlüssel läuft nie ab, und beendet wird er erst, wenn Sie den Host in der Oberfläche widerrufen.
Eine Sperre pro Profil verhindert, dass zwei Prozesse dieselbe Kopplung gleichzeitig ausführen — andernfalls würden sie sich gegenseitig in einer Schleife aus der WebSocket-Sitzung verdrängen.
Betreiben Sie den Client unter einer dedizierten Rolle, die auf das synchronisierte Schema beschränkt ist, damit ein kompromittiertes Token nichts anderes berühren kann – lassen Sie diese Rolle aber die Replikattabellen anlegen, damit sie ihr gehören. Die Migrationsanweisungen setzen Eigentümerschaft voraus, nicht Berechtigungen.
| Befehl | Was es tut |
|---|---|
| ee-database pair --server URL | Browser-bestätigtes Device-Code-Pairing. Wählen Sie aus, welche Datenbank synchronisiert werden soll. |
| ee-database pair --server URL <token> | Mit einem auf der Seite Database Sync ausgestellten Token koppeln (headless-tauglich). |
| ee-database run --dsn DSN [--save-dsn] [--skip-bootstrap] | Bootstrap aus dem Snapshot (sofern nicht übersprungen), dann verbinden und Deltas anwenden. |
| ee-database run … --create-missing | Legen Sie die Zieldatenbank zuerst an, falls sie nicht existiert – mit den Zugangsdaten des DSN selbst (postgres benötigt CREATEDB, mysql das CREATE-Recht). |
| ee-database run … --create-missing --admin-dsn DSN | Erstellen Sie über eine Admin-Verbindung alles, was der Ziel-DSN benennt: die fehlende Rolle/den fehlenden Benutzer (mit dem Passwort des DSN) und die zugehörige Datenbank. Der Ziel-DSN benötigt dann keine Erstellungsrechte; der Admin-DSN wird niemals gespeichert. |
| ee-database run --all | Jede gekoppelte Datenbank gleichzeitig aus einem Prozess synchronisieren (jede benötigt einen gespeicherten DSN). |
| ee-database run … --verbose | Schreibstruktur und Laufzeit jedes Deltas protokollieren, nicht nur die Zusammenfassung pro Fenster. Wird auch von host run akzeptiert. |
| ee-database host pair --server URL --dsn BASE_DSN [--admin-dsn DSN] <token> | Koppeln Sie diese Maschine einmalig als verwalteten Sync-Host — die Basis-DSN benennt Ihren Datenbankserver (ohne Datenbanknamen) und verlässt die Maschine nie; das Token stammt aus dem Dialog „Sync hosts“ (Symbolleisten-Schaltfläche „Sync hosts“ auf der Seite Database Sync). Ein Pairing pro Server: Koppeln Sie parallel mit mehreren Entity Enricher-Servern. |
| ee-database host run [--server URL] | Verwalteter Modus: Jede diesem Host zugewiesene Database Sync wird beansprucht, bei Bedarf angelegt und automatisch synchron gehalten – keine Kopplung pro Datenbank, sondern gleichzeitig über alle gekoppelten Server hinweg (--server beschränkt dies auf einen). Eine Datenbank, die bereits mit einem anderen Client gekoppelt ist, wird gemeldet und niemals übernommen. |
| ee-database host status / host disconnect [--server URL] | Zeigt die Host-Kopplungen dieses Rechners an oder entfernt sie. Serverseitig widerrufen Sie sie über die Karte „Sync-Hosts“. |
| ee-database status | Kopplungsstatus, Server-URL und die gekoppelten Datenbanken anzeigen. |
| ee-database disconnect | Lokale Anmeldedaten einer Kopplung löschen. Widerrufen Sie serverseitig über die Benutzeroberfläche. |
| ee-database version | Druckversion. |
Zugangsdaten werden mit Modus 600 gespeichert, ein Profil pro gekoppelter Datenbank, unter ~/.config/ee-database/profiles/ — koppeln Sie einmal pro Datenbank; mit --database NAME wählen Sie eine aus, wenn mehrere gekoppelt sind. Lieber ganz ohne Automatisierung? Derselbe Feed ist auch schlicht REST: GET /api/databases//changes, dann POST /api/databases//ack — siehe Database Sync.
Der Client ist MIT-lizenziert und liegt in einem öffentlichen Repository, sodass jeder genau prüfen kann, was gegen seine Datenbank ausgeführt wird.
Quelle: github.com/TOT-Concept/ee-database
Releases: github.com/TOT-Concept/ee-database/releases — jede Binärdatei wird vor der Veröffentlichung mit cosign signiert.
Installationsprogramm prüfen: curl -fsSL https://entityenricher.ai/install-eedatabase.sh | less