Erfahren Sie, wie Microframeworks Teams ermöglichen, maßgeschneiderte Architekturen mit klaren Modulen, Middleware und Grenzen zusammenzustellen — inklusive Abwägungen, Mustern und Fallstricken.

Microframeworks sind schlanke Web-Frameworks, die sich auf das Wesentliche konzentrieren: eine Anfrage empfangen, sie an den richtigen Handler routen und eine Antwort zurückliefern. Im Gegensatz zu Full-Stack-Frameworks bündeln sie in der Regel nicht alles, was man eventuell braucht (Admin-Panels, ORM/Database-Layer, Formular-Builder, Hintergrundjobs, vollständige Auth-Flows). Stattdessen bieten sie einen kleinen, stabilen Kern und lassen Sie nur das hinzufügen, was Ihr Produkt tatsächlich verlangt.
Ein Full-Stack-Framework ist wie der Kauf eines vollständig eingerichteten Hauses: konsistent und bequem, aber schwer zu remodeln. Ein Microframework ähnelt eher einem leeren, aber statisch soliden Raum: Sie entscheiden über Räume, Möblierung und Versorgung.
Diese Freiheit ist das, was wir mit maßgeschneiderter Architektur meinen — ein Systementwurf, der sich nach den Bedürfnissen Ihres Teams, Ihrer Domäne und Ihren Betriebsanforderungen richtet. Kurz gesagt: Sie wählen die Komponenten (Logging, Datenzugriff, Validierung, Auth, Hintergrundverarbeitung) und entscheiden, wie sie verbunden werden, anstatt eine vorgefertigte "eine richtige Art" zu akzeptieren.
Teams greifen häufig zu Microframeworks, wenn sie:
Wir konzentrieren uns darauf, wie Microframeworks modulare Gestaltung unterstützen: Bausteine zusammenstellen, Middleware einsetzen und Dependency Injection hinzufügen, ohne das Projekt in ein wissenschaftliches Experiment zu verwandeln.
Wir vergleichen keine spezifischen Frameworks zeilenweise und behaupten auch nicht, Microframeworks seien immer besser. Ziel ist es, Ihnen zu helfen, Struktur absichtlich zu wählen — und sie sicher weiterzuentwickeln, wenn sich Anforderungen ändern.
Microframeworks funktionieren am besten, wenn Sie Ihre Anwendung wie ein Kit behandeln, nicht wie ein vormontiertes Haus. Anstatt einen meinungsstarken Stack zu akzeptieren, starten Sie mit einem kleinen Kern und fügen Fähigkeiten nur hinzu, wenn sie sich bezahlt machen.
Ein praktischer "Kern" ist üblicherweise nur:
Das reicht, um einen funktionierenden API-Endpunkt oder eine Webseite auszuliefern. Alles andere ist optional, bis Sie einen konkreten Grund haben.
Wenn Sie Authentifizierung, Validierung oder Logging benötigen, fügen Sie sie als separate Komponenten hinzu — idealerweise hinter klaren Schnittstellen. Das hält Ihre Architektur verständlich: Jedes neue Teil sollte die Fragen beantworten „Welches Problem löst das?“ und „Wo wird es eingehängt?“.
Beispiele für "nur hinzufügen, was nötig ist"-Module:
Wählen Sie früh Lösungen, die Sie nicht einsperren. Bevorzugen Sie dünne Wrapper und Konfiguration statt tiefgreifender Framework-Magie. Wenn Sie ein Modul wechseln können, ohne Business-Logik umzuschreiben, sind Sie auf dem richtigen Weg.
Eine einfache Definition of Done für Architekturentscheidungen: Das Team kann den Zweck jedes Moduls erklären, es innerhalb eines Tages oder zweier ersetzen und unabhängig testen.
Microframeworks bleiben bewusst klein, was bedeutet, dass Sie die "Organe" Ihrer Anwendung wählen können, anstatt einen kompletten Körper zu übernehmen. Das macht maßgeschneiderte Architektur praktikabel: Sie können minimal starten und nur dann Teile hinzufügen, wenn ein echter Bedarf entsteht.
Die meisten Microframework-Apps starten mit einem Router, der URLs auf Controller (oder einfachere Request-Handler) abbildet. Controller können nach Feature (Billing, Accounts) oder nach Oberfläche (Web vs. API) organisiert werden, je nachdem, wie Sie den Code pflegen wollen.
Middleware umgibt typischerweise den Request/Response-Fluss und ist der beste Ort für Cross-Cutting-Concerns:
Da Middleware komponierbar ist, können Sie sie global anwenden (alles braucht Logging) oder nur für bestimmte Routen (Admin-Endpunkte benötigen strengere Auth).
Microframeworks zwingen selten eine bestimmte Datenebene auf, sodass Sie eine wählen können, die zu Ihrem Team und Workload passt:
Ein gutes Muster ist, den Datenzugriff hinter einem Repository- oder Service-Layer zu halten, sodass ein Werkzeugwechsel später nicht durch Ihre Handler durchschlägt.
Nicht jedes Produkt braucht asynchrone Verarbeitung von Tag Eins an. Wenn es nötig wird, fügen Sie einen Job-Runner und eine Queue hinzu (E-Mails, Videoverarbeitung, Webhooks). Behandeln Sie Hintergrundjobs wie einen separaten "Entry Point" in Ihre Domänenlogik und teilen Sie die gleichen Services wie die HTTP-Schicht, anstatt Regeln zu duplizieren.
Middleware liefert das größte Hebelpotential: Sie ermöglicht es, übergreifende Anforderungen — Dinge, die jede Anfrage betreffen — zu behandeln, ohne jeden Route-Handler aufzublähen. Ziel ist einfach: Handler bleiben auf Business-Logik konzentriert, Middleware übernimmt die Infrastruktur.
Statt dieselben Prüfungen und Header in jedem Endpoint zu wiederholen, fügen Sie Middleware einmal hinzu. Ein sauberer Handler könnte so aussehen: Eingabe parsen, Service aufrufen, Antwort zurückgeben. Alles andere — Auth, Logging, Validierungsvoreinstellungen, Antwortformatierung — kann davor oder danach passieren.
Reihenfolge ist Verhalten. Eine gängige, lesbare Sequenz ist:
Wenn Kompression zu früh läuft, kann sie Fehler verpassen; läuft Fehlerhandling zu spät, riskieren Sie, Stacktraces zu leaken oder inkonsistente Formate zurückzugeben.
X-Request-Id-Header und dessen Aufnahme in Logs.{ error, message, requestId }).Gruppieren Sie Middleware nach Zweck (Observability, Sicherheit, Parsing, Response-Shaping) und wenden Sie sie im richtigen Scope an: Global für wirklich universelle Regeln und Route-Group-Middleware für spezifische Bereiche (z. B. /admin). Benennen Sie jede Middleware klar und dokumentieren Sie die erwartete Reihenfolge in einem kurzen Kommentar in der Setup-Datei, damit zukünftige Änderungen das Verhalten nicht stillschweigend beschädigen.
Ein Microframework gibt Ihnen einen dünnen "Request rein, Response raus"-Kern. Alles andere — Datenbankzugriff, Caching, E-Mail, Drittanbieter-APIs — sollte austauschbar sein. Genau hier helfen Inversion of Control (IoC) und Dependency Injection (DI), ohne Ihre Codebasis in ein Wissenschaftsprojekt zu verwandeln.
Wenn ein Feature eine Datenbank braucht, ist es verlockend, sie direkt im Feature zu erzeugen ("new database client here"). Der Nachteil: Jeder Ort, der so "einkauft", ist jetzt fest an diesen speziellen DB-Client gebunden.
IoC kehrt das um: Ihr Feature fragt an, was es braucht, und das App-Wiring reicht es rein. Ihr Feature wird dadurch wiederverwendbarer und leichter änderbar.
Dependency Injection bedeutet einfach, Abhängigkeiten hereinzureichen statt sie intern zu erstellen. In einem Microframework-Setup geschieht das oft beim Start:
Sie benötigen keinen großen DI-Container, um die Vorteile zu erhalten. Beginnen Sie mit einer einfachen Regel: Erzeuge Abhängigkeiten an einer Stelle und reiche sie nach unten weiter.
Um Komponenten austauschbar zu machen, definieren Sie "was gebraucht wird" als kleine Schnittstelle und schreiben Adapter für konkrete Tools.
Beispielmuster:
UserRepository (Interface): findById, create, listPostgresUserRepository (Adapter): implementiert diese Methoden mit PostgresInMemoryUserRepository (Adapter): implementiert die gleichen Methoden für TestsIhre Business-Logik kennt nur UserRepository, nicht Postgres. Ein Austausch der Speicherung wird so zur Konfigurationsfrage, nicht zum Rewrite.
Dasselbe gilt für externe APIs:
PaymentsGateway-InterfaceStripePaymentsGateway-AdapterFakePaymentsGateway für lokale EntwicklungMicroframeworks machen es leicht, Konfiguration versehentlich zu verstreuen. Widerstehen Sie dem.
Ein wartbares Muster ist:
Das gibt Ihnen das Hauptziel: Komponenten austauschen, ohne die App umzuschreiben. Datenbankwechsel, Austausch eines API-Clients oder Einführung einer Queue wird so zu einer kleinen Änderung in der Wiring-Schicht — der Rest des Codes bleibt stabil.
Microframeworks zwingen nicht zu einer "eine wahre Art" Ihre Codebasis zu strukturieren. Stattdessen liefern sie Routing, Request/Response-Handling und wenige Extension-Points — so können Sie Muster wählen, die zu Teamgröße, Produktreife und Änderungsfrequenz passen.
Das vertraute, einfache Setup: Controller kümmern sich um HTTP, Services kapseln Business-Regeln und Repositories sprechen mit der Datenbank.
Passt gut, wenn Ihre Domäne überschaubar ist, das Team klein bis mittelgroß ist und Sie vorhersehbare Orte für Code wollen. Microframeworks unterstützen das natürlich: Routen mapen zu Controllern, Controller rufen Services auf und Repositories werden via leichter manueller Komposition verdrahtet.
Hexagonale Architektur eignet sich, wenn Ihr System länger leben soll als heutige Entscheidungen — DB, Message-Bus, Drittanbieter-APIs oder sogar die UI.
Microframeworks funktionieren gut hier, weil die "Adapter"-Schicht oft Ihre HTTP-Handler plus einer dünnen Übersetzungsebene in Domain-Commands ist. Ihre Ports sind Interfaces in der Domain, und Adapter implementieren sie (SQL, REST-Clients, Queues). Das Framework bleibt an der Peripherie, nicht im Zentrum.
Wenn Sie Microservice-ähnliche Klarheit ohne den betrieblichen Overhead wollen, ist ein modularer Monolith eine starke Option. Sie behalten eine einzige deploybare Einheit, teilen sie aber intern in Feature-Module (z. B. Billing, Accounts, Notifications) mit expliziten öffentlichen APIs.
Microframeworks erleichtern das, weil sie nicht automatisch alles verdrahten: Jedes Modul kann eigene Routen, Abhängigkeiten und Datenzugriffe registrieren, sodass Grenzen sichtbar bleiben und nicht versehentlich überschritten werden.
Über alle drei Muster bleibt der Vorteil derselbe: Sie wählen die Regeln — Ordnerstruktur, Abhängigkeitsrichtung und Modulgrenzen — während das Microframework eine kleine, stabile Oberfläche bereitstellt, an die Sie andocken.
Microframeworks machen es einfach, klein zu starten und flexibel zu bleiben, beantworten aber nicht die größere Frage: Welche "Form" soll Ihr System haben? Die richtige Wahl hängt weniger von Technologie ab und mehr von Teamgröße, Release-Takt und wie schmerzhaft Koordination geworden ist.
Ein Monolith wird als eine deploybare Einheit ausgeliefert. Er ist häufig der schnellste Weg zu einem funktionierenden Produkt: ein Build, ein Log-Set, ein Ort zum Debuggen.
Ein modularer Monolith ist weiterhin eine deploybare Einheit, intern aber in klare Module getrennt (Packages, Bounded Contexts, Feature-Ordner). Das ist oft der beste "nächste Schritt", wenn die Codebasis wächst — besonders mit Microframeworks, wo Module explizit bleiben können.
Microservices teilen die Deployables in mehrere Services. Das kann Kopplung zwischen Teams reduzieren, vervielfacht aber den betrieblichen Aufwand.
Splitten Sie, wenn eine Grenze schon real in Ihrer Arbeit ist:
Vermeiden Sie Splits, wenn es hauptsächlich Bequemlichkeit ist ("dieser Ordner ist groß") oder Services dieselben DB-Tabellen teilen müssten. Das ist ein Zeichen, dass Sie noch keine stabile Grenze gefunden haben.
Ein API-Gateway kann Clients vereinfachen (ein Einstiegspunkt, zentrale Auth/Rate-Limiting). Nachteil: Es kann zum Engpass und Single Point of Failure werden, wenn es zu schlau wächst.
Shared Libraries beschleunigen Entwicklung (gemeinsame Validierung, Logging, SDKs), schaffen aber versteckte Kopplung. Müssen mehrere Services gleichzeitig updaten, haben Sie einen verteilten Monolithen rekonstruiert.
Microservices bringen laufende Kosten: mehr Deploy-Pipelines, Versionierung, Service-Discovery, Monitoring, Tracing, Incident Response und On-Call-Rotationen. Wenn Ihr Team diese Maschinerie nicht komfortabel betreiben kann, ist ein modularer Monolith mit Microframework-Bausteinen oft die sicherere Architektur.
Ein Microframework schenkt Ihnen Freiheit, aber Wartbarkeit müssen Sie gestalten. Ziel ist, die "maßgeschneiderten" Teile leicht auffindbar, leicht austauschbar und schwer zu missbrauchen zu machen.
Wählen Sie eine Struktur, die Sie in einer Minute erklären können und mit Code-Reviews durchsetzen. Eine praktische Aufteilung ist:
app/ (Composition Root: verdrahtet Module)modules/ (Business-Capabilities)transport/ (HTTP-Routing, Request/Response-Mapping)shared/ (Cross-Cutting-Utilities: Config, Logging, Fehler-Typen)tests/Behalten Sie konsistente Benennung: Modul-Ordner nutzen Nomen (billing, users) und Einstiegspunkte sind vorhersehbar (index, routes, service).
Behandeln Sie jedes Modul wie ein kleines Produkt mit klaren Grenzen:
modules/users/public.ts)modules/users/internal/*)Vermeiden Sie "reach-through"-Imports wie modules/orders/internal/db.ts von einem anderen Modul. Wenn ein anderer Teil es braucht, promoten Sie es zur öffentlichen API.
Auch kleine Services brauchen Sichtbarkeit:
Legen Sie das in shared/observability ab, sodass jeder Route-Handler dieselben Konventionen nutzt.
Machen Sie Fehler für Clients vorhersehbar und für Menschen leicht zu debuggen. Definieren Sie eine Fehlerform (z. B. code, message, details, requestId) und einen Validierungsansatz (Schema pro Endpoint). Zentralisieren Sie die Abbildung interner Exceptions auf HTTP-Antworten, damit Handler auf Business-Logik fokussiert bleiben.
Wenn Ihr Ziel ist, schnell voranzukommen und gleichzeitig eine Microframework-ähnliche Architektur explizit zu halten, kann Koder.ai als Scaffold- und Iterationstool nützlich sein, weniger als Ersatz für gutes Design. Beschreiben Sie Modulgrenzen, Middleware-Stack und Fehlerformat im Chat, generieren Sie eine funktionierende Basis-App (z. B. React-Frontend mit Go + PostgreSQL Backend) und verfeinern Sie dann bewusst das Wiring.
Zwei Funktionen passen besonders gut zur Arbeit an kundenspezifischer Architektur:
Da Koder.ai Source-Code-Export unterstützt, behalten Sie Besitz der Architektur und entwickeln sie in Ihrem Repo wie bei einem handgebauten Microframework-Projekt weiter.
Microframework-basierte Systeme können sich "handmontiert" anfühlen — Tests sind dann weniger ein Framework-Thema und mehr Schutz für die Nahtstellen zwischen Teilen. Ziel ist Vertrauen, ohne jede Änderung in einen vollständigen End-to-End-Lauf zu verwandeln.
Starten Sie mit Unit-Tests für Business-Regeln (Validierung, Preisberechnung, Berechtigungslogik), weil sie schnell sind und Fehler präzise lokalisieren.
Investieren Sie dann in eine kleinere Anzahl hochpriorisierter Integrationstests, die das Wiring abdecken: Routing → Middleware → Handler → Persistence-Boundary. Diese fangen subtile Bugs, die beim Zusammenspiel entstehen.
Middleware verbirgt oft Cross-Cutting-Verhalten (Auth, Logging, Rate Limits). Testen Sie sie wie eine Pipeline:
Für Handler testen Sie bevorzugt die öffentliche HTTP-Form (Statuscodes, Header, Response-Body) statt interner Funktionsaufrufe. Das hält Tests stabil, wenn sich Interna ändern.
Nutzen Sie DI (oder einfache Konstruktorparameter), um reale Abhängigkeiten gegen Fakes zu tauschen:
Wenn mehrere Services oder Teams von einer API abhängen, fügen Sie Contract Tests hinzu, die Request/Response-Erwartungen absichern. Provider-seitige Vertragstests stellen sicher, dass Sie Konsumenten nicht versehentlich brechen, selbst wenn sich Microframework-Setup und interne Module entwickeln.
Microframeworks geben Ihnen Freiheit, aber Freiheit ist nicht automatisch Klarheit. Die Hauptgefahren treten später auf — wenn das Team wächst, die Codebasis zunimmt und "temporäre" Entscheidungen dauerhaft werden.
Bei weniger eingebauten Konventionen können zwei Teams dieselbe Funktion in unterschiedlichem Stil implementieren (Routing, Fehlerhandling, Response-Formate, Logging). Diese Inkonsistenz verlangsamt Reviews und erschwert Onboarding.
Eine einfache Leitplanke hilft: Schreiben Sie ein kurzes "Service Template"-Dokument (Projektstruktur, Namensgebung, Fehlerformat, Logging-Felder) und erzwingen Sie es mit einem Starter-Repo und ein paar Lints.
utils/-WucherMicroframework-Projekte starten oft sauber und sammeln dann einen utils/-Ordner, der stillschweigend zu einem zweiten Framework wird. Wenn Module Helfer, Konstanten und globalen Zustand teilen, verschwimmen Grenzen und Änderungen führen zu überraschenden Fehlern.
Bevorzugen Sie explizite Shared-Pakete mit Versionierung oder halten Sie das Teilen minimal: Typen, Schnittstellen und gut getestete Primitiven. Wenn ein Helfer Geschäftsregeln benötigt, gehört er wahrscheinlich in ein Domain-Modul, nicht in utils.
Wenn Sie Auth, Autorisierung, Input-Validierung und Rate Limiting manuell verdrahten, ist es leicht, eine Route zu vergessen, Middleware zu übersehen oder nur "Happy-Path"-Inputs zu validieren.
Zentralisieren Sie Sicherheitsdefaults: sichere Header, konsistente Auth-Prüfungen und Validierung an der Peripherie. Fügen Sie Tests hinzu, die behaupten, dass geschützte Endpunkte tatsächlich geschützt sind.
Ungeplante Middleware-Layer erhöhen Overhead — besonders, wenn mehrere Middlewares Bodies parsen, Speicher abfragen oder Logs serialisieren.
Halten Sie Middleware klein und messbar. Dokumentieren Sie die Standard-Reihenfolge und prüfen Sie neue Middleware auf Kosten. Wenn Sie Bloat vermuten, profilieren Sie Anfragen und entfernen Sie redundante Schritte.
Microframeworks bieten Optionen — aber Optionen brauchen einen Entscheidungsprozess. Ziel ist nicht die "beste" Architektur, sondern eine Form, die Ihr Team bauen, betreiben und ändern kann, ohne Drama.
Bevor Sie zwischen Monolith und Microservices wählen, beantworten Sie:
Wenn Sie unsicher sind, defaulten Sie auf einen modularen Monolithen mit Microframework. Er hält Grenzen klar und bleibt gleichzeitig einfach auszuliefern.
Microframeworks erzwingen Konsistenz nicht für Sie, also legen Sie Konventionen früh fest:
Eine einseitige "Service Contract"-Datei in /docs reicht oft aus.
Starten Sie mit Cross-Cutting-Stücken, die Sie überall brauchen:
Behandeln Sie diese als Shared-Module, nicht als kopierte Snippets.
Architekturen sollten sich mit Anforderungen ändern. Überprüfen Sie vierteljährlich, welche Deploys langsamer werden, welche Teile unterschiedlich skalieren und was am häufigsten bricht. Wenn eine Domäne zum Engpass wird, ist das Ihr Kandidat zum Split — nicht das ganze System.
Ein Microframework-Setup startet selten "fertig designt". Meist beginnt es mit einer API, einem Team und einem engen Zeitplan. Der Wert zeigt sich, wenn das Produkt wächst: neue Features kommen, mehr Menschen berühren den Code und Ihre Architektur muss dehnbar sein, ohne zu reißen.
Sie starten mit einem minimalen Service: Routing, Request-Parsing und einem DB-Adapter. Die meiste Logik lebt nahe an den Endpoints, weil es schneller ist.
Mit Auth, Payments, Notifications und Reporting trennen Sie diese in Module (Ordner/Packages) mit klaren öffentlichen Schnittstellen. Jedes Modul besitzt seine Modelle, Business-Regeln und Datenzugriffe und exponiert nur, was andere Module brauchen.
Logging, Auth-Prüfungen, Rate Limiting und Request-Validierung wandern in Middleware, damit jeder Endpoint konsistent verhält. Weil Reihenfolge wichtig ist, sollten Sie sie dokumentieren.
Dokumentieren Sie:
Refaktorieren Sie, wenn Module zu viele Interna teilen, Build-Zeiten deutlich langsamer werden oder kleine Änderungen Änderungen in vielen Modulen erfordern.
Erwägen Sie Servicesplits, wenn Teams durch gemeinsame Deploys blockiert sind, Teile unterschiedlich skalieren müssen oder eine Integrationsgrenze sich bereits wie ein eigenes Produkt verhält.
Microframeworks eignen sich, wenn Sie die Anwendung um Ihre Domäne herum formen wollen statt um einen vorgegebenen Stack. Sie passen besonders zu Teams, die Klarheit über Bequemlichkeit stellen: Sie sind bereit, ein paar Bausteine bewusst zu wählen (und zu pflegen) im Austausch für eine Codebasis, die verständlich bleibt, wenn Anforderungen sich ändern.
Ihre Flexibilität zahlt sich nur aus, wenn Sie sie mit ein paar Gewohnheiten schützen:
Starten Sie mit zwei leichten Artefakten:
Dokumentieren Sie Entscheidungen kurz — auch kurze Notizen helfen. Legen Sie eine "Architecture Decisions"-Seite im Repo an und prüfen Sie sie regelmäßig, damit gestrige Abkürzungen nicht zu heutigen Beschränkungen werden.
Ein Microframework konzentriert sich auf das Wesentliche: Routing, Request-/Response-Verarbeitung und grundlegende Erweiterungspunkte.
Ein Full-Stack-Framework liefert meist viele "Batterien inklusive" (ORM, Auth, Admin, Formulare, Hintergrundjobs). Microframeworks tauschen Bequemlichkeit gegen mehr Kontrolle — Sie fügen nur das hinzu, was Sie wirklich brauchen, und bestimmen selbst, wie die Teile verbunden werden.
Microframeworks passen, wenn Sie:
Ein "kleinster nützlicher Kern" besteht meist aus:
Starten Sie damit, liefern Sie einen Endpunkt und ergänzen Sie Module nur, wenn sie ihren Nutzen wirklich zeigen (Auth, Validierung, Observability, Queues).
Middleware ist ideal für übergreifende Anliegen, z. B.:
Route-Handler sollten sich auf Business-Logik konzentrieren: parse → service aufrufen → response zurückgeben.
Reihenfolge ändert Verhalten. Eine gängige, verlässliche Abfolge ist:
Dokumentieren Sie die Reihenfolge in der Nähe des Setup-Codes, damit zukünftige Änderungen das Verhalten oder die Sicherheit nicht stillschweigend brechen.
Inversion of Control bedeutet: Ihr Business-Code erstellt seine Abhängigkeiten nicht selbst (er geht nicht "einkaufen"). Stattdessen stellt das App-Wiring zur Laufzeit zur Verfügung, was gebraucht wird.
Praktisch: bauen Sie DB-Client, Logger und HTTP-Clients beim Start und geben Sie sie an Services/Handler weiter. Das reduziert enge Kopplung und erleichtert Testen und Austausch von Implementierungen.
Nein. Die meisten DI-Vorteile erhalten Sie mit einer einfachen Composition-Root:
Fügen Sie ein Container-Pattern nur hinzu, wenn der Abhängigkeitsgraph manuell unhandlich wird — beginnen Sie nicht standardmäßig mit zusätzlicher Komplexität.
Leg die Speicherung und externe APIs hinter kleine Schnittstellen (Ports) und implementiere Adapter:
UserRepository-Interface mit findById, create, listPostgresUserRepository für ProduktionEine praktische Struktur, die Grenzen sichtbar hält:
app/ Composition Root (Wiring)modules/ Feature-Module (Domain-Fähigkeiten)transport/ HTTP-Routing + Request/Response-Mappingshared/ Config, Logging, Fehler-Typen, ObservabilitySetzen Sie auf schnelle Unit-Tests für Business-Regeln und wenige, wertvolle Integrationstests, die die Pipeline (Routing → Middleware → Handler → Persistence-Boundary) abdecken.
Nutzen Sie DI/Fakes, um externe Dienste zu isolieren, und testen Sie Middleware wie eine Pipeline (Header, Seiteneffekte, Blocking-Verhalten). Wenn mehrere Teams APIs konsumieren, fügen Sie Vertragstests (Contract Tests) hinzu, um Breaking Changes zu vermeiden.
InMemoryUserRepository für TestsHandler/Services hängen von der Schnittstelle ab, nicht vom konkreten Tool. Ein Wechsel der Datenbank oder des Drittanbieters wird so zur Konfigurations-/Wiring-Änderung und nicht zum Rewrite.
tests/Durchsetzten Sie öffentliche Modul-APIs (z. B. modules/users/public.ts) und vermeiden Sie "reach-through"-Imports in Interna.