Ein Software-Stack für vierzig Services: warum wir dabei bleiben
Was ein fester Stack dem Auftraggeber bringt, was er uns kostet – und wo wir davon abweichen
· 5 Min. · Architektur, TypeScript, PostgreSQL, Arbeitsweise
Unser Software-Stack ist seit Jahren derselbe: TypeScript, Nuxt 4, Node.js, PostgreSQL 16 mit pgvector, Claude als Sprachmodell. Über vierzig Services laufen auf dieser Kombination – Kundenprojekte ebenso wie die Werkzeuge, mit denen wir unser eigenes Unternehmen steuern. Warum wir dabei bleiben, was das dem Auftraggeber bringt und wo die Entscheidung nicht mehr trägt.
Ein Software-Stack für alles: die Entscheidung dahinter
Ein Softwarehaus mit mehreren Stacks klingt flexibler. In der Praxis heißt es: drei Arten von Build-Pipelines, drei Sätze von Deploy-Skripten, drei Wege, wie Secrets, Migrationen und Logs aussehen. Jeder Entwickler kennt ein Drittel davon gut. Bei Urlaub, Krankheit oder Kündigung fehlt dann nicht ein Mensch, sondern das Wissen über ein Drittel der Systeme.
Wir haben uns für das Gegenteil entschieden: eine Architektur, die sich in allen Services wiederholt. Dieselbe Ordnerstruktur, derselbe Weg vom Formular über den Server in die Datenbank, dieselbe Art, wie ein geplanter Job nachts läuft und wie ein Sprachmodell aufgerufen wird. Ob ein Service eine Buchhaltungsschnittstelle anbindet oder ein Kundenportal ausliefert, ist dann ein Unterschied im Inhalt, nicht in der Form.
Die Auswahl selbst ist weniger spektakulär als ihre Konsequenz. Nuxt, weil ein Framework Serverseite, Rendering und statische Ausgabe abdeckt und wir es täglich betreiben. TypeScript im strikten Modus, weil der Compiler die erste Reviewrunde übernimmt. PostgreSQL, weil es mit jsonb, Volltext und pgvector drei Aufgaben erledigt, für die sonst drei Systeme nötig wären. Jede dieser Entscheidungen könnte man anders treffen. Nicht verhandelbar ist, dass es eine Entscheidung ist und nicht fünf.
Was Einarbeitung an einem Tag konkret heißt
Der wichtigste Effekt betrifft Menschen, nicht Technik. Ein Entwickler, der lange an einem unserer internen Werkzeuge gearbeitet hat, öffnet ein Kundenprojekt zum ersten Mal und findet sich am selben Tag zurecht. Er weiß, wo die Datenbankschicht liegt, wie Validierung aussieht, woher Umgebungsvariablen kommen und welche Prüfungen vor einem Merge laufen. Lernen muss er die Fachlichkeit des Kunden – den Teil, der ohnehin niemandem erspart bleibt.
Diesen einen Tag halten wir für einen der wertvollsten Posten in unserer Kalkulation. Bei drei Stacks wäre daraus ein Monat geworden, und dieser Monat stünde entweder auf der Rechnung des Kunden oder verschwände in unserer Marge. Beides ist schlecht: Das eine ist unfair, das andere führt dazu, dass an der Einarbeitung gespart wird und Fehler in Produktion landen.
Dazu kommt ein Nebeneffekt, den wir erst später verstanden haben: Auch die Sprachmodelle, mit denen unsere Entwickler arbeiten, profitieren von der Gleichförmigkeit. Ein Modell mit Kontext aus vierzig gleich gebauten Services schlägt beim nächsten den vorhandenen Aufbau vor, statt einen neuen zu erfinden. Unsere 63 dokumentierten Prozeduren setzen genau darauf: Sie beschreiben, wie eine Aufgabe in dieser Architektur gelöst wird, und gelten für alle Projekte.
Was Auftraggeber von einem einheitlichen Software-Stack haben
Für einen CTO, der ein Vorhaben an uns vergibt, übersetzt sich die eine Grundlage in vier Zusagen. Wir können sie halten, weil sie in der Struktur stecken und nicht vom guten Willen einzelner abhängen.
- Kein Stillstand, wenn jemand ausfällt. Fällt der Entwickler aus, der Ihr Modul baut, übernimmt ein Kollege, der dieselbe Architektur täglich vor sich hat. Es gibt keine Phase, in der jemand erst hineinfinden muss – übergeben werden die Fachlichkeit und das offene Ticket.
- Reviews, die etwas prüfen. Ein Review ist nur so gut wie die Vertrautheit des Reviewers mit dem Code. Bei einer Grundlage liest jeder bei uns jeden Pull Request, und die automatischen Prüfungen – Build, Tests, Sprachdateien, Fähigkeitenkatalog – sind für alle Projekte dieselben.
- Schätzungen aus Erfahrung. Wenn eine Anbindung zum zehnten Mal nach demselben Muster entsteht, ist die Schätzung eine Erinnerung und keine Hoffnung. Viele unserer 67 fertigen Konnektoren sind so entstanden: einmal gebaut, im nächsten Projekt wiederverwendet.
- Übergabefähigkeit. Falls Sie das Ergebnis später mit eigenen Leuten weiterentwickeln, übernehmen Sie eine Codebasis mit einer Struktur, die in jedem unserer Services gleich ist – und nicht die Handschrift eines einzelnen Entwicklers.
Wie wir diese Zusagen vertraglich fassen – als Werk mit Abnahme oder als Beratung nach Tagen –, steht auf der Seite Softwareentwicklung für den Mittelstand.
Warum PostgreSQL für fast alles reicht
Der Teil des Stacks, über den wir am häufigsten diskutieren, ist die Datenbank. Die Frage kommt meist so: „Braucht ihr für die KI-Funktionen nicht eine Vektordatenbank?“ Die Antwort: PostgreSQL mit pgvector ist eine. Wir speichern Einbettungen neben den Fachdaten, in derselben Transaktion, mit denselben Rechten und demselben Backup. Für die Suche kombinieren wir Vektorähnlichkeit, klassischen Volltext und Trigramme in einer Abfrage. Ein zweites System für Vektoren brächte einen zweiten Betrieb, eine zweite Synchronisation und einen zweiten Fehlerfall.
Dasselbe gilt für flexible Strukturen. Bevor wir ein Dokumentensystem einführen, nutzen wir jsonb-Spalten – für Konfigurationen, Rohdaten aus Fremdsystemen, alles, was noch nicht stabil genug für ein festes Schema ist. Wird die Struktur stabil, wandert sie in Spalten. Innerhalb eines Systems ist dieser Weg ein Refactoring; zwischen zwei Systemen wäre er eine Migration.
Wo eine andere Grundlage die bessere Antwort ist
Ein fester Stack ist eine Stärke, solange man ihn nicht zur Weltanschauung macht. Drei Situationen, in denen wir davon abweichen oder abraten:
- Das System existiert bereits – und funktioniert. Ein gewachsenes Java- oder .NET-Backend schreiben wir nicht um, weil wir Node bevorzugen. Wir bauen daneben: Automatisierung, Portal und KI-Schicht sprechen über REST oder Ereignisse mit dem Bestand. Die Prozessautomatisierung ist fast immer so gebaut, und was dabei an technischen Schulden im Altsystem bleibt, benennen wir im Angebot, statt es mit einer Neuentwicklung zu überdecken.
- Der Kern der Aufgabe ist numerisch. Wo eine Aufgabe vor allem aus Statistik, Modelltraining oder wissenschaftlichem Rechnen besteht, ist das Python-Ökosystem zu Hause. Solche Komponenten binden wir an, statt sie in TypeScript nachzubauen.
- Ihr Team lebt in einer anderen Welt. Wenn Ihre Leute das Ergebnis dauerhaft weiterpflegen sollen und ausschließlich PHP oder Java schreiben, ist ein TypeScript-Projekt ein Fremdkörper, egal wie sauber es gebaut ist. Dann sagen wir das im ersten Gespräch und empfehlen im Zweifel einen klar getrennten Service mit einer Schnittstelle, den Ihre Leute nutzen, ohne ihn anfassen zu müssen.
Was wir nicht tun: einen Stack anbieten, den wir nicht selbst jeden Tag betreiben, nur um einen Auftrag zu bekommen. Das würde genau den Vorteil zerstören, von dem dieser Beitrag handelt.
Weitere Beiträge
Sagen Sie uns, was am Ende da sein soll
Sie schildern die Aufgabe, wir sagen offen, ob sie zu uns passt. Passt sie nicht, nennen wir Ihnen den Grund.