Integration von Benachrichtigungen mit Novu: Lohnt es sich?

Lars wuethrich portrait 2024 04 02 155534 mkvs
Lars wuethrich portrait 2024 04 02 155534 mkvs
Lars Wüthrich Software Engineer

Moderne Software-Lösungen informieren die Benutzer:innen über wichtige Ereignisse wie Kommentare, Deadlines oder Handlungen anderer Nutzenden. Solche Benachrichtigungen verbessern die User Experience - zumindest wenn sie sinnvoll umgesetzt sind.

Doch die Einführung eines Benachrichtigungssystems wirft zahlreiche Fragen auf: Welche Kanäle sollten genutzt werden? Über welche Ereignisse soll informiert werden? Welche Person soll eine Benachrichtigung erhalten?

In der Regel sind In-App-Benachrichtigungen, E-Mails und mobile Push-Benachrichtigungen geeignet. Manchmal können jedoch auch SMS-Benachrichtigungen oder die Integration mit anderen externen Systemen der richtige Kanal sein. Ausserdem muss festgelegt werden, welche Ereignisse kritisch sind und welche nicht. Benutzer:innen soll ja nicht durch eine Flut an Benachrichtigungen überfordert werden. Andernfalls sinkt der Wert einer Benachrichtigung, wenn sie einfach ignoriert wird. Diese Flut an Benachrichtigungen kann beispielsweise vermieden werden indem häufige Ereignisse in einer einzigen Benachrichtigung zusammengefasst werden.

Deshalb haben wir uns gefragt, ob es möglich ist einen externen Dienst zu verwenden, der die meisten oder alle diese Probleme löst. Denn ohne eine fixfertige Lösung müssten folgende Punkte selber implementiert und unterhalten werden:

  • API-Integration für jeden Kommunikationskanal
  • Individuelle Vorlagen für die Benachrichtigung pro Kanal
  • Aggregation von Nachrichten (Message Digest), um ähnliche Benachrichtigungen, die innerhalb eines kurzen Zeitraums gesendet werden, zu gruppieren und dadurch Spamming zu vermeiden.
  • Ein Datenmodell für die Benachrichtigungen und eine interne API für Aktionen wie das Erstellen, Lesen, Aktualisieren und Löschen (CRUD) von Benachrichtigungen. Auch Aktionen zum Markieren von Benachrichtigungen als gelesen oder ungelesen müssten selber umgesetzt werden.
  • Ein In-App Posteingang zur Darstellung der Benachrichtigungen im Frontend.
  • Verlinkung von der Benachrichtigung zum Ort des Ereignisses in der Anwendung

Im Rahmen der Entwicklung von Caturix, einer Projektmanagement Software für die Baubranche, haben wir ein solches Benachrichtigungssystem eingebunden. Caturix adressiert mehrere Herausforderungen, mit denen Bauunternehmen täglich konfrontiert sind: Projektmanagement, Schicht- und Ressourcenplanung und die Kollaboration zwischen den Personen im Büro und auf der Baustelle. Ein sinnvolles Benachrichtigungssystem kann in diesen Anwendungsfällen sehr hilfreich sein.

Inbox
Inbox

Wir haben uns bei der Umsetzung für eine Art duales System entschieden, die Anwender:innen über Änderungen über mehrere Kanäle benachrichtigt und ihnen die Möglichkeit gibt, Massnahmen zu ergreifen. Das Postfach dient zudem als Liste mit Erinnerungen an Aufgaben, die erledigt werden müssen. Dieser To-Do-Ansatz haben wir explizit angestrebt, weil wir der Meinung sind, dass eine Benachrichtigung nur hilfreich ist, wenn darauf eine Handlung folgt.

Die Benachrichtigungen werden über verschiedene Kanäle wie E-Mail, Push, SMS und In-App versendet. Die Anwender:innen können dabei wählen, welche Benachrichtigungen über welchen Kanal versendet werden sollen.

Evaluation von Novu

Wir haben diverse Lösungen evaluiert und uns für die Lösung von Novu entschieden. Novu ist eine Open Source Lösung, welche die Infrastruktur für ein Benachrichtigungssystem zur Verfügung stellt. Novu ermöglicht die Anbindung von E-Mail-, SMS-, Chat- und Push-Kanälen. Für die In-App-Integration wird das Client-SDK oder die Server-API verwendet.

Da Caturix noch ein junges Startup ist und sich schnell entwickelt, schien Novu ein gutes Preis/Leistungsverhältnis zu haben. Die Business-Lizenz umfasst 60'000 Events und kostet um die 200 US-Dollar pro Monat. Wir erreichen zwar diese Event-Limite aktuell noch nicht, doch für die Übersetzung der Benachrichtigungen in verschiedene Sprachen ist die teurere Lizenz notwendig. In der Schweiz, einem mehrsprachigen Land ein absolutes Muss. Es wäre wünschenswert gewesen, wenn die Internationalisierung in der unteren Preisstufe enthalten wäre. Allerdings wurde diese Funktion erst gerade veröffentlicht und wird noch aktiv entwickelt (Stand März 2024). Sie entspricht im Moment nicht unseren Anforderungen, so dass wir in der unteren Preisstufe bleiben können.

Es gibt andere Lösungen mit ähnlichen Funktionen und einem höheren Reifegrad. Für uns erfüllte Novu unsere Kriterien gut genug und auch bei den Kosten konnte es sich von alternativen Lösungen abheben. Ausserdem ist Novu Open Source und wir könnten es selbst hosten, wenn wir wollten.

Im folgenden Artikel wollen wir dir einen groben Überblicke über die verschiedenen Teile von Novu geben und auf die technischen Herausforderungen eingehen mit denen wir bei der Integration von Novu konfrontiert waren - denn davon gab es einige. Am Ende des Artikel sollst du besser abschätzen können, ob es sich für dich lohnt Novu zu integrieren.

Hauptmerkmale von Novu

Es gibt drei Hauptfunktionen, die bei der Evaluation berücksichtigt wurden - abgesehen von den wettbewerbsfähigen Preisen.

  • Einfaches Hinzufügen von Providern: Novu unterstützt eine Vielzahl von Providern für jeden Kanaltyp und vereinfacht den Prozess durch die unkomplizierte Eingabe von API-Schlüsseln und Konfigurationen.
  • Message Digest: Das Versenden von Benachrichtigungen über die API ist mit jedem Backend einfach zu bewerkstelligen. Novu bietet jedoch eine Funktion namens Message Digest, die sehr praktisch ist. Es ist möglich einen Digest-Zeitraum festlegen und alle Nachrichten, die innerhalb dieses Zeitraums gesendet werden zu einer einzigen Nachricht zusammenzufassen. Durch das Zusammenfassen von Nachrichten wird Spam vermieden.
  • Client SDK und Webhook: Wir umgingen die Standard-Nachrichtenkomponente von Novu und nutzten das Headless-Javascript-Paket mit dem wir eine benutzerdefinierte Komponente erstellen konnten. Für sehr einfache Anwendungsfälle kann die mitgelieferte Komponente von Novu ausreichend sein.

Preisgestaltung

Der Preis richtet sich nach der Anzahl der Ereignisse pro Monat und scheint im Vergleich zu anderen Benachrichtigungsdiensten recht günstig zu sein. Wenn die Übersetzungsfunktion besser gewesen wäre, hätten wir uns für die Business-Lizenz entschieden, aber diese Funktion befindet sich derzeit noch in der aktiven Entwicklung. Das bedeutete jedoch, dass wir einen Teil der Vorlagenerstellung und Übersetzungsarbeit selbst übernehmen mussten, was den Nutzen von Novu in dieser Hinsicht schmälerte.

Pricing novu
Pricing novu

Novu's Server-Side SDKs

Novu bietet sowohl serverseitige SDKs für die Verwaltung von Subscriber, deren Präferenzen und die Auslösung von Benachrichtigungen aus dem Backend als auch clientseitige SDKs, die eine Schnittstelle zu den Webhook- und vorgefertigten Frontend-Komponenten bilden. Die clientseitigen SDKs ermöglichen es Benachrichtigungen anzeigen oder Präferenzen zu setzen.

Zum Zeitpunkt der Erstellung dieses Artikels hat Novu serverseitige SDKs für:

Technologie

NodePhpLaravelPythonKotlinJavaRubyGoC#

Für einen detaillierteren Einblick in die serverseitige SDK empfehlen wir Novu's SDK Dokumentation. Weitere Informationen zur API sind in der Novu API-Referenz zu finden.

Der Vorteil dieser SDKs ist beträchtlich. Sie machen die manuelle Erstellung von Datenübertragungsobjekten überflüssig, sowohl für die gesendeten Argumente als auch für die von der API empfangenen Daten. Dadurch wird das Fehlerpotenzial reduziert, das bei der manuellen Erstellung von REST-Anfragen häufig auftritt. Während alternative Dienste ihr Angebot mit Postman- oder Insomnia-Sammlungen für API-Tests ergänzen, stellt Novu derzeit keine Sammlung bereit.

Unsere Erfahrungen mit dem Kotlin-SDK waren grösstenteils positiv, auch wenn einige gravierende Einschränkungen zu beachten sind. Das SDK scheint nicht vollständig mit den neuesten API-Änderungen aktualisiert zu sein. Dieses Defizit führt zu fehlenden Feldern, so dass wir gelegentlich gezwungen waren, REST-Anfragen manuell zu schreiben. Darüber hinaus ist eine Reihe von Argumenten im SDK entweder nicht typisiert oder es handelt sich um einfache Strings. Somit mussten wir die erforderlichen Argumente anhand der REST-API-Endpunkte ableiten.

Ein grosses Problem der Novu-API ist das Fehlen bestimmter Funktionen, die für die Entwicklung indivdiueller Benachrichtigungskomponenten im Frontend entscheidend sind. So fehlt dem API-Endpunkt für den Abruf von Nachrichten (Get Messages) die Möglichkeit, Benachrichtigungen u. a. nach ihrem Status "gelesen" oder "ungelesen" zu filtern. Darüber hinaus unterstützt die API nur das Löschen einzelner Benachrichtigungen und nicht das Löschen von Massenmeldungen oder aller Benachrichtigungen. Das kann in bestimmten Szenarien eine Einschränkung darstellen.

Es macht den Anschein, dass sich die Entwicklungsbemühungen von Novu mehr auf die Client-Komponenten konzentriert haben. Das hat zur Folge, dass einige Funktionen ausschliesslich in der Client-API verfügbar und nicht dokumentiert sind. Diese Konzentration auf das Client-SDK zeigt sich auch in der Server-API, die für bestimmte Aufgaben nur eine begrenzte Funktionalität aufweist.

Um diese Einschränkungen zu umgehen, haben wir auf die Verwendung der undokumentierten Client-API auf der Serverseite zurückgegriffen. Diesen Ansatz haben wir durch den Quellcode des Headless JavaScript SDK entdeckt und obwohl diese Schnittstelle mehr Funktionen als in der offiziellen API-Referenz beschrieben bietet, ist es leider keine ideale Lösung.

Zusammenfassend lässt sich sagen, dass die benutzerdefinierten Komponenten und das Client-SDK von Novu für einfache Anwendungsfälle ausreichen. Für komplexere Anwendungsfälle gibt es jedoch Einschränkungen, wenn das benutzerdefinierte Client-SDK für eine bestimmte Programmiersprache nicht verfügbar ist. Es liegt auf der Hand, dass die Server-API von Novu von einer weiteren Entwicklung und einer Anpassung an die Fähigkeiten der Client-SDKs profitieren könnte.

Novu's Client-Side SDKs

Es gibt vorgefertigte Komponenten, die für verschiedene Tech-Stacks bereitgestellt werden.

Technologie

Komponente

VueVorgefertigtAngularVorgefertigtReactVorgefertigtFlutterNicht vorhandenWeb-componentVorgefertigtIframe embeddedVorgefertigtHeadlessIndividuell
Novu component
Novu component

Diese vorgefertigten Komponenten eignen sich zwar für einige Anwendungen und bieten ein gewisses Mass an Anpassungsmöglichkeiten, entsprechen aber möglicherweise nicht vollständig den spezifischen Anforderungen. In unserem Fall entwickelten wir eine eigenen Komponente, um den Posteingang mit dem To-Do-Charakter abzubilden. Generell kann es in Anbetracht der inhärenten Beschränkungen von Novu schnell möglich sein, dass eine individuelle Komponente notwendig wird.

Für eine solche individuelle Entwicklung kann das Headless-Paket verwendet werden. Es ermöglicht eine Websocket-Verbindung zu Novu herzustellen und bietet folgende Funktionen:

  • Achten auf Änderungen bei ungelesenen oder ungesehenen Benachrichtigungen
  • Benachrichtigungen abrufen basierend auf Paginierung (Diese ist fehlerhaft und wird später diskutiert)
  • Ermöglicht das Markieren von Nachrichten als gelesen
  • Ermöglicht die Aktualisierung von Benutzereinstellungen
  • Ermöglicht das Löschen aller Benachrichtigungen oder einer einzelnen Benachrichtigung

Trotz einiger Probleme mit der Paginierung beim Abrufen von Benachrichtigungen kann der Headless-Service von Novu effektiv zur Erstellung einer eigenen benutzerdefinierten Komponente verwendet werden.

Das Novu Web UI

Es gibt eine API zur Konfiguration von Workflows. Jedem Benachrichtigungstyp ist ein Workflow zugeordnet indem die verfügbaren Kanäle konfiguriert und Vorlagen für Benachrichtigungen festgelegt werden. Eine Vorlage kann gewisse Parameter wie Benutzername oder weitere Infos enthalten. Die Vorlage-Engine ist dokumentiert unter: Workflow Editor und Handlebars & Helpers. Handlebar.js wird zum Einfügen von Daten in die Vorlagen verwendet.

Das Problem bei diesem Ansatz ist, dass er im Grunde gegen die "Infrastructure as Code"-Philosophie verstösst. Wenn die Konfiguration über mehrere Benutzeroberflächen verteilt ist, leidet die Transparenz und Nachvollziehbarkeit von Änderungen. Für die Erstellung einiger dieser Objekte wird eine API angeboten. Diese ist jedoch kaum dokumentiert und daher schwer zu verwenden.

Der Vorteil des Web UI ist, dass Nachrichtenvorlagen angepasst oder Kanäle konfiguriert werden können, ohne dass das Backend neu deployed werden muss. Das ist sehr praktisch. Zudem können auch bestimmte Benachrichtigungen und Kanäle innerhalb der Benutzeroberfläche deaktiviert werden, ohne dass ein Update erforderlich ist.

Umgebungen

Derzeit unterstützt Novu nur zwei Umgebungen. Die Entwicklungsumgebung zum Testen und die eigentliche Produktionsumgebung. Wenn mehr als zwei Umgebungen verwendet werden (z.B. Dev, Test, Prod), muss die Entwicklungsumgebung über mehrere Umgebungen geteilt werden. Das erschwert das Testen, da die Benachrichtigungen von mehreren Umgebung stammen können.

Darüber hinaus erlaubt Novu keine unterschiedlichen Konfigurationen für die Entwicklungs- und Produktionsumgebung. Dadurch wird die Konsistenz zwischen diesen beiden Umgebungen gewährleistet. Eine Einschränkung liegt vor, wenn für die Entwicklungsumgebung eine andere Konfiguration notwendig ist, weil dies nachträglich nicht mehr möglich ist. Um Änderungen in der Produktionsumgebung zu implementieren, müssen diese zunächst getestet und dann aus der Entwicklungsumgebung übertragen werden. Durch diesen Prozess wird sichergestellt, dass nur geprüfte Änderungen in der Produktionsumgebung implementiert werden.

Dokumentation

Die Dokumentation von Novu ist unter folgendem Link zu finden: Dokumentation

Die Kernfunktionen des Services werden gut beschrieben. Jedoch ist die API in vielen Fällen nicht ausreichend dokumentiert, wodurch die Integration aufwändiger wird.

Übersetzungen

Novu ermöglicht es Benachrichtigungen zu übersetzen. Jedoch ist die Funktion sehr neu und in aktiver Entwicklung (Stand März 2024). Die Funktion erscheint deshalb auch als "early access feature" und das merkt man auch bei der Umsetzung, weil es nicht nahtlos in das Templating-System integriert ist. Ohne Übersetzung kann für jeden Kanal eine Vorlage definiert werden, die spezifische Daten enthält und zusätzlich die Handlebar-Templating-Sprache für die Kompilierung von Nachrichten verwendet. Wenn jedoch Übersetzungen eingebunden werden sollen, müssen i18n-Übersetzungsdateien bereitgestellt werden. Dies erfordert jedoch die Verwendung einer anderen Syntax (benutzerdefinierte Handlebar-Helfer), um die Übersetzungen in die Nachricht einzubinden. Ausserdem gibt es keine Autovervollständigung für die Übersetzungsschlüssel.

Da die derzeitige Lösung unsere Anforderungen nicht erfüllte, haben wir uns entschieden vorerst unsere eigene Templating-Sprache im Backend zu verwenden. Das hat seine Nachteile und schmälert den Nutzen von Novu etwas. Deshalb können wir Novu nicht empfehlen, wenn Übersetzungen für zahlreiche Kanäle notwendig sind. Zumindest bis die Implementierung verfeinert wurde.

Sicherheit

Was die Sicherheit betrifft, so wird die Kommunikation mit der Novu-API durch die Verwendung einer für jede Umgebung ("Entwicklung" und "Produktion") eindeutigen Anwendungskennung sowie eines API-Schlüssels verwaltet, der über das entsprechende Web UI neu generiert werden kann.

Ausserdem bietet Novu eine Frontend-Komponente, die Benachrichtigungen auf der Client-Seite anzeigt. Das erfordert einen Sicherheitsmechanismus, um sicherzustellen, dass Benutzer:innen nur auf ihre eigenen Benachrichtigungen zugreifen können. Clients können eine WebSocket-Verbindung unter Verwendung der Anwendungskennung (nicht des API-Schlüssels) und einer Subscriber-ID herstellen. Um die Sicherheit zu erhöhen, erlaubt Novu die Verwendung eines HMAC-Hashes als Voraussetzung. Dies bedeutet, dass Clients einen HMAC-signierten Hash der Subscriber-ID zusammen mit der ID selbst übergeben müssen, um die WebSocket-Verbindung herzustellen.

Dieser Hash ist jedoch statisch und hängt nur von dem API-Secret ab. Sollte dies durchsickern, muss der API-Schlüssel neu generiert werden, um zu verhindern, dass jemand auf die Benachrichtigungen eines anderen Nutzers zugreift.

Novu integrieren oder selbst entwickeln?

Die Frage, ob eine Lösung selbst entwickelt oder auf bestehende Lösungen wie die Novu-API für Benachrichtigungen zurückgegriffen werden soll, ist immer eine Herausforderung. Die technischen Hürden werden von Softwareentwickler:innen oft unterschätzt. Daher gehe ich bei dieser Analyse vorsichtig vor, da ich mir bewusst bin, dass einige technische Herausforderungen möglicherweise erst im Laufe des Entwicklungsprozesses deutlich werden. Deshalb ist die folgende Einschätzung mit Vorsicht zu geniessen.

  • Datenmodell und API für Benachrichtigungen: Dieser Aspekt scheint weniger Fallstricke zu haben. Er umfasst die Erstellung einer Meldung in der Datenbank und die Verwaltung aller CRUD-Vorgänge, einschliesslich "als gelesen markieren" und "als ungelesen markieren". Die Integration mit Novu war jedoch weniger einfach als erwartet. Die Einschränkungen der API und das Fehlen bestimmter Funktionen in der Backend- oder Client-API führten zu Stolpersteinen. Eine selbst entwickelte Lösung hätte möglicherweise eine reibungslosere Integration mit unserer Flutter-App ermöglicht, zumal Novu über kein Flutter/Dart-SDK verfügt. Letzteres war uns jedoch bewusst.
  • Channel API Integration: Dieser Schritt ist relativ einfach, da er die Erstellung von API-Anfragen zur Versendung von Benachrichtigungen beinhaltet. Novu bietet zwar einige Effizienzvorteile, aber ein Wechsel der Lösung oder wesentliche Änderungen können erhebliche Anpassungen erforderlich machen. Die Zeitersparnis in diesem Bereich ist meiner Meinung nach bei der Auswahl einer Lösung zu vernachlässigen.
  • Frontend Komponente: Die mitgelieferte Standardkomponente entsprach nicht unseren spezifischen Anforderungen. Wir haben deshalb eine eigene Frontend-Komponente für die Anzeige von Benachrichtigungen entwickelt. Somit haben wir dadurch keine Zeit eingespart.
  • Message Digest und Templating: Dieser Bereich birgt wahrscheinlich die meisten technischen Herausforderungen, wenn dies selber entwickelt werden soll. Die Verwaltung von Benachrichtigungen, vor allem in Zeiten hoher Last, erfordert die Überwachung, Aggregation und den Versand von Benachrichtigungen erst nach einer bestimmten Zeit der Inaktivität. Das Aggregieren von Nachrichten und das Erstellen von benutzerdefinierten Vorlagen für diese Benachrichtigungen würde wahrscheinlich einen erheblichen Teil der Entwicklungszeit in Anspruch nehmen. Ausserdem könnten in diesem Fall zusätzliche technische Probleme auftauchen.
    Der einzige Vorteil, den wir bei einer eigenen Implementierung hätten, ist, dass die derzeitige Anzahl der versendeten Benachrichtigungen recht gering ist, so dass die Skalierbarkeit im Moment kein wichtiges Thema für die Implementierung wäre.
  • UI für die Konfiguration der Workflows: Die Entwicklung einer Benutzeroberfläche zur Verwaltung aller Benachrichtigungen und Workflow-Änderungen könnte zeitaufwändig sein. Das würde womöglich die meiste Zeit in Anspruch nehmen, wenn wir eine Benutzeroberfläche für alle unsere Benachrichtigungen und Änderungen an den Arbeitsabläufen haben möchten. In diesem Zusammenhang bin ich jedoch der Meinung, dass diese Funktion für unseren Anwendungsfall nicht notwendig gewesen wäre. Das Hinzufügen neuer Ereignisse erfordert auch Backend-Änderungen, und die Konfiguration innerhalb des Codes würde auch der "Infrastructure As Code"-Philosophie folgen, was ebenfalls von Vorteil gewesen wäre.

Zusammenfassend lässt sich sagen, dass die Nutzung der Novu-API eine gewisse Zeitersparnis mit sich brachte. Insbesondere durch die Message-Digest-Funktion und die einfache Konfiguration der Channel-Provider. Die Herausforderungen, die sich aufgrund der Einschränkungen und Besonderheiten der API-Implementierung ergaben, lassen jedoch die benutzerdefinierte Implementierung im Nachhinein als praktikabler erscheinen. Da wir unter anderem auch einige Backend-Endpunkte für unsere Flutter-App schreiben mussten, ist davon auszugehen, dass die Zeit- und Aufwandsersparnis insgesamt nicht so gross war wie erhofft.

Pros- und Kontras

Pro

Kontra

Effektive Message Digest FunktionÜbersetzungsfunktion ist in der jetzigen Form noch nicht fertigGrosse Auswahl an vorgefertigten Integrationen für jeden KanalDie API könnte besser gestaltet und umfassender seinVerfügbarkeit von Server-SDKsMangelnde Funktionsgleichheit zwischen der Server-API und den Client-SDK-Endpunkten.Wettbewerbsfähige PreiseFehlende Flutter/Dart SDKServer-SDKs, insbesondere für Kotlin, sind nicht ganz auf dem neuesten Stand und es fehlt an TypisierungAbweichung von der "Infrastructure as Code"-PhilosophieUngünstige Trennung zwischen Entwicklungs- und Produktionsumgebung, die nicht unterschiedlich konfiguriert werden können

Fazit

Im Wesentlichen bietet Novu einen funktionalen Service zu einem wettbewerbsfähigen Preis. Wenn die Benutzer:innen mit einem UI-zentrierten Konfigurationsansatz vertraut sind, erweist er sich als wertvolles Werkzeug. Das Design der API und einige ungelöste Probleme sind jedoch bemerkenswerte Nachteile. Nichtsdestotrotz ist die einfache Konfiguration mehrerer Kanäle eine zeitsparende Funktion.

Das grosse Manko ist die Übersetzungsunterstützung. Sie scheint nicht gut in die Vorlagenerstellung und die Message Digest Engine integriert zu sein. Ausserdem ist die Funktion noch sehr neu und im März 2024 gibt es noch einige Probleme. Wenn du also viele Ereignistypen mit Übersetzungen verwalten musst, würde ich aktuell davon abraten, Novu zu wählen.

Jetzt abonnieren für exklusive Einblicke in die Softwareentwicklung

Kein Spam und kein Blabla. Jederzeit abbestellen.