Dirora
Zurück zum Blog
Engineering

Wie wir unsere Microservices-Architektur aufgebaut haben

Dirora Team10. April 20268 min read

Dirora ist API-first und basiert auf mehr als 40 Go-Microservices – ein Service pro Domäne, jeder verantwortlich für einen bestimmten Ausschnitt der Commerce-Plattform: Produkte, Bestellungen, Zahlungen, Storefronts, Abonnements, Analysen und mehr. Dieser Beitrag ist eine ehrliche Rundreise aus der Vogelperspektive durch die Entscheidungen hinter diesem Backend: warum wir die Werkzeuge gewählt haben, die wir gewählt haben, wie wir verhindern, dass Dutzende beweglicher Teile im Chaos enden, und was wir jedem Team raten würden, das ein mandantenfähiges SaaS-Produkt von Grund auf aufbaut. Es ist für Ingenieure geschrieben, die neugierig sind, was unter der Haube steckt, sollte aber auch dann verständlich sein, wenn Sie nie eine Zeile Go geschrieben haben.

Nichts davon ist Architektur um der Architektur willen. Jede Entscheidung unten lässt sich auf etwas zurückführen, das ein Händler spürt: Seiten, die schnell laden, Checkouts, die nicht doppelt abbuchen, Uploads, denen nie der Platz ausgeht, und eine Plattform, die weiterläuft, während wir darunter Änderungen ausliefern. Wenn Sie sehen möchten, wie sich diese Grundlagen in das übersetzen, was Sie mit einem Shop tatsächlich tun können, ist unsere Funktionsübersicht das händlerorientierte Gegenstück zu diesem Beitrag.

Warum Go?

Früh haben wir drei Sprachen ernsthaft evaluiert – Node.js, Rust und Go – denn die Wahl der Laufzeitumgebung prägt alles Weitere. Jede hatte echte Stärken, und keine war ein offensichtlicher Verlierer.

  • Node.js hat ein riesiges Ökosystem, einen leichten Einstellungspool und eine Syntax, die jedem vertraut ist, der Frontend-Code geschrieben hat. Aber CPU-lastige Arbeit – Bildverarbeitung, Verschlüsselung, Erzeugung großer Berichte – konkurriert auf einer Single-Thread-Event-Loop mit der Anfragenverarbeitung, und die fehlende Typsicherheit zur Laufzeit äußert sich eher in subtilen Produktionsfehlern als in Fehlern zur Kompilierzeit.

  • Rust bietet erstklassige Performance und Speichersicherheit ohne Garbage Collector. Die Kompromisse in unserer Phase waren langsamere Kompilierzeiten, eine steilere Lernkurve für neue Mitwirkende und ein Async-Ökosystem, das sich zu unserem Start noch setzte. Für einen Systemkern ist Rust hervorragend; für eine große Fläche gewöhnlicher Geschäftslogik, die sich wöchentlich ändert, fühlten sich die Kosten hoch an.

  • Go gab uns ein Nebenläufigkeitsmodell, mit dem zu arbeiten wirklich angenehm ist – Goroutinen sind günstig genug, dass man Tausende starten kann, ohne über Thread-Pools nachzudenken – plus schnelle Kompilierzeiten und eine bewusst kleine Sprache, die neue Ingenieure innerhalb von Tagen lesen und zu der sie beitragen können. Ihre Standardbibliothek deckt das meiste ab, was ein Web-Backend braucht, ohne für jede Aufgabe eine Abhängigkeit einzubinden.

Go gewann, weil es für das optimiert, was am wichtigsten ist, wenn man breit aufbaut und sich schnell bewegt: Entwicklungsgeschwindigkeit, ohne die Laufzeit-Performance aufzugeben. Eine kleine, lesbare Codebasis, in der sich ein neuer Ingenieur am zweiten Tag zurechtfindet, ist über die Lebensdauer eines Produkts mehr wert, als die letzten paar Prozent Durchsatz herauszupressen. Dieses performante Go-Backend ist auch der Grund, warum unsere Storefronts unter Last schnell rendern – etwas, das wir in unserem Leitfaden zur Optimierung der Shop-Performance vertiefen.

Ein Service pro Domäne

Das zentrale Ordnungsprinzip ist einfach: Jeder Service besitzt genau eine Geschäftsdomäne, und er besitzt sein eigenes Datenbankschema. Der Produktservice besitzt Produkte; der Bestellservice besitzt Bestellungen; Zahlungen, Abonnements, Storefront-Rendering, Analysen und der Rest leben jeweils hinter ihrer eigenen Grenze. Kein Service greift in die Tabellen eines anderen Services. Braucht der Bestellservice Produktdaten, fragt er den Produktservice über eine definierte Schnittstelle – er führt nie direkt eine Abfrage gegen Produkttabellen aus.

Diese Isolation ist die Disziplin, die ein wachsendes System wartbar hält. Weil niemand still von der internen Form der Tabellen eines anderen abhängen kann, können wir die Speicherung eines Services umbauen, seine Indizes ändern oder seine Logik überarbeiten, ohne versehentlich fünf andere Services zu brechen. Die Grenze ist der Vertrag. Sie kostet anfangs etwas mehr – man schreibt eine API, wo ein Monolith einen Join schreiben würde – aber sie zahlt sich jedes Mal aus, wenn eine Domäne sich unabhängig weiterentwickeln muss. Weil die Plattform API-first ist, werden dieselben Domänenservices Entwicklern über eine öffentliche REST-API, anbieterneutrale Webhooks, eine CLI und den Theme-Editor bereitgestellt – die Storefront- und Admin-Apps sind lediglich Clients derselben API, gegen die auch Sie entwickeln können. Wenn Sie auf Dirora aufbauen, behandelt unser Beitrag zu API-first, Headless Commerce diese entwicklerorientierte Seite.

Wie Services miteinander kommunizieren

Services kommunizieren über HTTP mit JSON, authentifiziert für interne Service-zu-Service-Aufrufe mit einem gemeinsamen internen Schlüssel. Wir haben REST bewusst schwereren Binärprotokollen vorgezogen, zumindest solange das System noch Gestalt annahm: Jeder Endpunkt ist mit gewöhnlichen Werkzeugen inspizierbar, leicht nachzuvollziehen und einfach zu debuggen, wenn um 2 Uhr nachts etwas schiefläuft. Es hat echten Wert, einen Produktionsaufruf von Hand reproduzieren zu können, statt Spezialwerkzeuge zu brauchen, um ihn zu dekodieren.

Wo zwei Services wirklich synchron bleiben müssen – eine Bestellung, die bezahlt wird, ein Abonnement, das sich verlängert – setzen wir auf Events und Webhooks statt auf enge, synchrone Aufrufketten. Die Regel, zu der wir immer wieder zurückkehren, ist, dass eine Anfrage sich nicht in eine lange Abhängigkeitskette auffächern sollte, in der ein langsamer Service alles über ihm herunterzieht. Lose Kopplung ist nicht bloß ein Architektur-Schlagwort; sie verhindert, dass ein Schluckauf in einer Ecke der Plattform zu einem Ausfall überall wird.

Typsicherer Datenzugriff und versionierte Migrationen

Für den Datenbankzugriff generieren wir typsicheren Go-Code aus handgeschriebenem SQL, statt zu einem schwergewichtigen ORM zu greifen. Das SQL selbst zu schreiben hält Abfragen transparent und optimierbar, während die Codegenerierung ganze Fehlerklassen abfängt – eine umbenannte Spalte, einen falschen Typ, ein fehlendes Argument – zur Kompilierzeit statt in der Produktion. Es ist der Königsweg zwischen rohen String-Abfragen und einem ORM, das verbirgt, was wirklich geschieht.

Schemaänderungen laufen über versionierte, nur vorwärts gerichtete Migrationen. Jede Änderung an der Datenbank ist ein nummerierter, geprüfter Schritt, der sich vorhersehbar über Umgebungen hinweg anwenden lässt, sodass das Schema vor einem Kunden nie ein Rätsel ist. In Kombination mit dem Besitz pro Service bedeutet das, dass jedes Team sein eigenes Datenmodell nach eigenem Zeitplan weiterentwickeln kann, ohne ein riesiges koordiniertes Release.

Mandantenfähigkeit ohne das Problem lauter Nachbarn

Dirora ist von Grund auf mandantenfähig: Viele unabhängige Shops teilen sich dieselbe Plattform, bleiben aber strikt voneinander isoliert. Diese Isolation richtig hinzubekommen – sodass ein ausgelasteter Shop einen anderen nie sehen, verlangsamen oder beeinflussen kann – ist einer der schwierigsten und wichtigsten Teile des Systems und verdient eine eigene Betrachtung. Wir haben das Modell ausführlich in Wie wir Mandantenfähigkeit handhaben beschrieben, das erklärt, wie die Mandantenidentität durch den Stack fließt und wie wir die Daten jedes Shops abgeschottet halten.

Dasselbe Design lässt einen einzelnen Shop grenzüberschreitend agieren – mehrere Währungen, mehrere Sprachen und lokalisierte Storefronts – ohne die zugrunde liegenden Services zu forken. Falls das für Ihr Geschäft relevant ist, zeigen unser Leitfaden zu Mehrwährung und Mehrsprachigkeit und der Beitrag zur KI-Übersetzung mit einem Klick, wie das aus Sicht des Händlers aussieht.

Speicherarchitektur

Alle hochgeladenen Dateien – Produktbilder, Theme-Assets, digitale Downloads – liegen in S3-kompatiblem privatem Objektspeicher statt auf der Festplatte eines einzelnen Servers. Das Design ist kapazitätsbewusst: Die Assets jedes Shops sind logisch getrennt, und ein Auswahlschritt leitet neue Uploads zu dem Speicher mit dem meisten verfügbaren Spielraum, sodass wir die Kapazität reibungslos erweitern können, während Händler mehr Produkte und Medien hinzufügen. Systemebene-Assets werden von Mandantendaten getrennt gehalten.

Der praktische Nutzen für Händler ist, dass Speicher keine Wand ist, gegen die man läuft. Das Hochladen von Bildern konkurriert nicht mit dem Live-Traffic Ihres Shops, Dateien werden effizient ausgeliefert, und die Plattform kann ihren Speicherbedarf hinter den Kulissen skalieren, ohne Ausfallzeit oder eine Migration, die Sie je bemerken würden. Automatische Bildoptimierung sitzt darüber, sodass die großen Fotos, die Sie hochladen, in angemessen dimensionierten, schnell ladenden Versionen ausgeliefert werden.

Storefronts schnell rendern

Kundenorientierte Storefronts werden serverseitig gerendert, was bedeutet, dass das Erste, was der Browser eines Käufers empfängt, echtes, anzeigebereites HTML ist statt einer leeren Seite, die auf JavaScript wartet. Das ist aus zwei Gründen wichtig: Es ist schneller für den Käufer, und es ist für Suchmaschinen lesbar, was zu einem großen Teil der Grund ist, warum Dirora-Storefronts mit starken SEO-Grundlagen und integrierten strukturierten Daten kommen. Geschwindigkeit ist im Handel keine Eitelkeitskennzahl – sie hängt direkt damit zusammen, wie viele Besucher zu Käufern werden.

Observability und Zuverlässigkeit

Man kann ein verteiltes System, das man nicht sehen kann, nicht betreiben, daher waren Metriken, strukturiertes Logging und Fehlererfassung von früh an Teil der Plattform, statt später angeflanscht zu werden. Wenn über einem Dutzend Services etwas schiefgeht, hängt der Unterschied zwischen einer Fünf-Minuten-Behebung und einer Fünf-Stunden-Untersuchung fast ausschließlich davon ab, ob man in Observability investiert hat, bevor man sie brauchte.

Zuverlässigkeit kommt auch aus einer einfachen, unglamourösen Disziplin: alles idempotent machen. Webhook-Handler, Hintergrundjobs, Zahlungs-Callbacks und Migrationen sind alle so geschrieben, dass sie zweimal auszuführen sicher ist. Netzwerke wiederholen Versuche, Nachrichten werden erneut zugestellt, und Nutzer doppelklicken. Anzunehmen, dass jede Operation mehr als einmal geschehen könnte – und sicherzustellen, dass sie dabei keinen Schaden anrichtet – ist das, was doppelte Bestellungen, doppelte Abbuchungen und korrupten Zustand verhindert.

Was das für Händler bedeutet

Architektur ist unsichtbar, wenn sie funktioniert, was genau der Sinn ist. Die Auszahlung von all dem Obigen ist eine Plattform, die unter Last schnell bleibt, die Daten jedes Shops isoliert hält und es uns erlaubt, kontinuierlich Verbesserungen auszuliefern, ohne Sie zu bitten, irgendetwas zu migrieren. Es ist auch das, was uns erlaubt, unser Geschäftsmodell sauber zu halten: Dirora berechnet bei keinem Tarif Transaktionsgebühren. Der einzige Abzug ist eine kleine Plattformgebühr, die mit Ihrem Wachstum sinkt – 1,5 % beim kostenlosen Starter-Tarif, 0,75 % bei Pro, 0,25 % bei Business und 0 % bei Enterprise – je mehr Sie also verkaufen, desto weniger nehmen wir. Gute Technik ist das, was ein faires, einfaches Preismodell tragfähig macht statt eines Marketingversprechens, das wir nicht halten können.

Gelernte Lektionen

  1. Investieren Sie in gemeinsame Grundlagen. Eine gemeinsame interne Bibliothek für Middleware, Fehlerbehandlung, Datenbank-Helfer, Speicherung und Health-Checks bedeutet, dass sich jeder Service konsistent verhält. Im großen Maßstab ist Konsistenz über Services hinweg mehr wert als die Unabhängigkeit jedes Teams.

  2. Bevorzugen Sie generierten, typsicheren Datenzugriff. SQL von Hand zu schreiben und typisierten Code daraus zu generieren, ist angenehmer in der Arbeit und sicherer als rohe String-Abfragen oder ein schweres ORM.

  3. Fügen Sie Observability hinzu, bevor Sie sie brauchen. Metriken, strukturierte Logs und Fehlererfassung vom ersten Tag an sparen weit mehr Zeit, als sie kosten. Man kann nicht debuggen, was man nicht sehen kann.

  4. Machen Sie alles idempotent. Wenn eine Operation zweimal laufen kann – und in einem verteilten System wird sie das irgendwann – machen Sie das zweimalige Ausführen harmlos.

  5. Ziehen Sie Grenzen und verteidigen Sie sie. Eine Domäne pro Service, ein Schema pro Service, kein Übergreifen über die Wand. Die Disziplin ist am ersten Tag lästig und am zweihundertsten Tag unbezahlbar.

Wenn Sie die Plattform sehen möchten, die diese Entscheidungen hervorgebracht haben – vom visuellen Theme-Editor bis zu eigenen Domains mit automatischem SSL – ist die Funktionsseite der richtige Startpunkt, und wenn Sie uns gegen Alternativen abwägen, legt unser ehrlicher Plattformvergleich die Kompromisse dar.

Häufig gestellte Fragen

In welcher Sprache ist Diroras Backend geschrieben?

Diroras Backend ist in Go gebaut, organisiert als API-first-Plattform aus mehr als 40 Microservices – einer pro Domäne –, gegen die Entwickler über eine öffentliche REST-API entwickeln können. Wir wählten Go wegen seiner leichtgewichtigen Nebenläufigkeit, schnellen Kompilierzeiten und lesbaren Codebasis, die es uns zusammen ermöglichen, eine breite Plattform schnell zu bauen, ohne die Laufzeit-Performance zu opfern.

Warum Microservices statt einer einzigen Anwendung verwenden?

Die Plattform in mehr als 40 Services nach Domänen aufzuteilen – Produkte, Bestellungen, Zahlungen, Storefronts und so weiter – bedeutet, dass jeder Teil sich unabhängig weiterentwickeln, skalieren und beheben lässt, ohne den Rest zu gefährden. Jeder Service besitzt sein eigenes Datenbankschema und fragt nie direkt die Tabellen eines anderen Services ab, was das System beim Wachsen wartbar hält und es uns erlaubt, die gesamte Plattform über eine konsistente öffentliche REST-API bereitzustellen.

Wo werden die Bilder und Dateien meines Shops gespeichert?

Hochgeladene Dateien liegen in S3-kompatiblem privatem Objektspeicher, wobei die Assets jedes Shops logisch getrennt sind und die Kapazität automatisch verwaltet wird. Speicher skaliert hinter den Kulissen, sodass das Hochladen weiterer Produkte und Medien nie mit dem Live-Traffic Ihrer Storefront konkurriert.

Wie hält Dirora verschiedene Shops voneinander isoliert?

Dirora ist von Grund auf mandantenfähig, mit strikter Isolation, sodass ein Shop nie die Daten oder Performance eines anderen sehen oder beeinflussen kann. Wir behandeln die Details in unserem eigenen Beitrag dazu, wie wir Mandantenfähigkeit handhaben.

Wirkt sich diese Architektur darauf aus, was ich zahle?

Ja, auf gute Weise. Dirora berechnet bei keinem Tarif Transaktionsgebühren. Der einzige Abzug ist eine kleine Plattformgebühr, die mit Ihrem Wachstum sinkt – 1,5 % bei Starter, 0,75 % bei Pro, 0,25 % bei Business und 0 % bei Enterprise. Effiziente Technik ist das, was diese Preisgestaltung tragfähig macht.

architecturegomicroservices

Sind Sie bereit, Ihren Shop einzurichten?

Kostenlos loslegen – keine Kreditkarte erforderlich.

Los geht’s