[{"data":1,"prerenderedAt":97},["ShallowReactive",2],{"content:blog:ein-stack-vierzig-services":3,"content:blog":34},{"slug":4,"title":5,"subtitle":6,"date":7,"metaTitle":8,"metaDescription":9,"excerpt":10,"readingMinutes":11,"tags":12,"toc":17,"body":33},"ein-stack-vierzig-services","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","2026-08-25","Ein Software-Stack für vierzig Services","Ein Software-Stack für über vierzig Services: TypeScript, Node.js, PostgreSQL. Was Auftraggeber in der DACH-Region von dieser Entscheidung haben.","Über vierzig Services laufen bei uns auf derselben Kombination aus TypeScript, Nuxt 4, Node.js und PostgreSQL mit pgvector. Wir schreiben auf, warum ein Entwickler dadurch am ersten Tag in einem fremden Projekt arbeiten kann, was ein Auftraggeber konkret davon hat – und in welchen drei Fällen wir selbst zu einer anderen Grundlage raten.",5,[13,14,15,16],"Architektur","TypeScript","PostgreSQL","Arbeitsweise",[18,21,24,27,30],{"id":19,"text":20},"entscheidung","Ein Software-Stack für alles: die Entscheidung dahinter",{"id":22,"text":23},"einarbeitung","Was Einarbeitung an einem Tag konkret heißt",{"id":25,"text":26},"auftraggeber","Was Auftraggeber von einem einheitlichen Software-Stack haben",{"id":28,"text":29},"postgres","Warum PostgreSQL für fast alles reicht",{"id":31,"text":32},"grenzen","Wo eine andere Grundlage die bessere Antwort ist","\u003Cp>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.\u003C\u002Fp>\n\n\u003Ch2 id=\"entscheidung\">Ein Software-Stack für alles: die Entscheidung dahinter\u003C\u002Fh2>\n\u003Cp>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.\u003C\u002Fp>\n\u003Cp>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.\u003C\u002Fp>\n\u003Cp>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.\u003C\u002Fp>\n\n\u003Ch2 id=\"einarbeitung\">Was Einarbeitung an einem Tag konkret heißt\u003C\u002Fh2>\n\u003Cp>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.\u003C\u002Fp>\n\u003Cp>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.\u003C\u002Fp>\n\u003Cp>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 dokumentierten Prozeduren setzen genau darauf: Sie beschreiben, wie eine Aufgabe in dieser Architektur gelöst wird, und gelten für alle Projekte.\u003C\u002Fp>\n\n\u003Ch2 id=\"auftraggeber\">Was Auftraggeber von einem einheitlichen Software-Stack haben\u003C\u002Fh2>\n\u003Cp>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.\u003C\u002Fp>\n\u003Cul>\n\u003Cli>\u003Cstrong>Kein Stillstand, wenn jemand ausfällt.\u003C\u002Fstrong> 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.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Reviews, die etwas prüfen.\u003C\u002Fstrong> 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.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Schätzungen aus Erfahrung.\u003C\u002Fstrong> Wenn eine Anbindung zum zehnten Mal nach demselben Muster entsteht, ist die Schätzung eine Erinnerung und keine Hoffnung. Viele unserer fertigen Konnektoren sind so entstanden: einmal gebaut, im nächsten Projekt wiederverwendet.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Übergabefähigkeit.\u003C\u002Fstrong> 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.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>Wie wir diese Zusagen vertraglich fassen – als Werk mit Abnahme oder als Beratung nach Tagen –, steht auf der Seite \u003Ca href=\"\u002Fleistungen\u002Fsoftwareentwicklung\">Softwareentwicklung für den Mittelstand\u003C\u002Fa>.\u003C\u002Fp>\n\n\u003Ch2 id=\"postgres\">Warum PostgreSQL für fast alles reicht\u003C\u002Fh2>\n\u003Cp>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.\u003C\u002Fp>\n\u003Cp>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.\u003C\u002Fp>\n\n\u003Ch2 id=\"grenzen\">Wo eine andere Grundlage die bessere Antwort ist\u003C\u002Fh2>\n\u003Cp>Ein fester Stack ist eine Stärke, solange man ihn nicht zur Weltanschauung macht. Drei Situationen, in denen wir davon abweichen oder abraten:\u003C\u002Fp>\n\u003Col>\n\u003Cli>\u003Cstrong>Das System existiert bereits – und funktioniert.\u003C\u002Fstrong> 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 \u003Ca href=\"\u002Fleistungen\u002Fprozessautomatisierung\">Prozessautomatisierung\u003C\u002Fa> ist fast immer so gebaut, und was dabei an \u003Ca href=\"\u002Flexikon\u002Ftechnische-schulden\">technischen Schulden\u003C\u002Fa> im Altsystem bleibt, benennen wir im Angebot, statt es mit einer Neuentwicklung zu überdecken.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Der Kern der Aufgabe ist numerisch.\u003C\u002Fstrong> 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.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Ihr Team lebt in einer anderen Welt.\u003C\u002Fstrong> 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.\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Cp>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.\u003C\u002Fp>",[35,61,89],{"slug":36,"title":37,"subtitle":38,"date":39,"metaTitle":40,"metaDescription":41,"excerpt":42,"readingMinutes":11,"tags":43,"toc":46},"senior-vakanz-bleibt-offen","Softwareentwicklung: Unternehmen mit offener Senior-Stelle haben drei Wege","Weitersuchen, Freelancer oder Werkvertrag mit einem eigenen Team – was jeder Weg kann und was nicht","2026-09-04","Senior-Stelle bleibt offen: drei Wege statt Warten","Die Senior-Stelle in der Softwareentwicklung bleibt offen, Reviews stauen sich: drei Wege für Unternehmen in der DACH-Region und die Frage, wann welcher passt.","Ein Entwicklungsteam mit einer Handvoll Leuten, eine unbesetzte Senior-Stelle, Pull Requests, die auf Reviews warten. Wir vergleichen drei Wege – weitersuchen, ein Freelancer für ein abgegrenztes Thema, ein Werkvertrag mit einem eigenen Team – und schreiben auf, wann welcher passt. Einer davon ist unser Geschäft; die anderen beiden sind oft trotzdem die richtige Antwort.",[16,44,45],"Werkvertrag","Engineering-Management",[47,50,53,56,59],{"id":48,"text":49},"kosten","Softwareentwicklung: Unternehmen zahlen die offene Stelle doppelt",{"id":51,"text":52},"weg-1","Weg 1: weitersuchen – aber anders",{"id":54,"text":55},"weg-2","Weg 2: ein Freelancer für ein abgegrenztes Thema",{"id":57,"text":58},"weg-3","Weg 3: Werkvertrag mit einem eigenen Team",{"id":19,"text":60},"Softwareentwicklung – Unternehmen entscheiden nach der Aufgabe",{"slug":62,"title":63,"subtitle":64,"date":65,"metaTitle":66,"metaDescription":67,"excerpt":68,"readingMinutes":11,"tags":69,"toc":73},"fuenf-jahre-bestellhistorie-ins-crm","Datenmigration ins CRM: fünf Jahre Bestellhistorie, keine Dublette","Wie wir einen Import so bauen, dass man ihn zweimal laufen lassen kann – und warum ein Archiv-Flag der wichtigste Teil war","2026-09-01","Datenmigration ins CRM: ohne eine einzige Dublette","Migration einer Shop-Historie in ein CRM auf PostgreSQL: idempotenter Import, Abgleich über E-Mail und Telefon, Archiv-Flag gegen Mailings an Altkunden.","Im CRM eines Lebensmittelherstellers mit Onlineshop standen 3 814 Bestellungen, im Shop lagen fünf Jahre Historie. Wir beschreiben, wie der Import idempotent wurde, wie Kontakte über E-Mail und Telefon zusammengeführt wurden und warum ein einfaches Archiv-Flag verhindert hat, dass die Automatik Altkunden anschreibt.",[70,71,15,72],"Migration","CRM","Praxisbericht",[74,77,80,83,86],{"id":75,"text":76},"ausgangslage","Die Lücke: 3 814 von 19 686",{"id":78,"text":79},"risiken","Drei Dinge, die bei einer Datenmigration ins CRM brechen",{"id":81,"text":82},"idempotenz","Derselbe Importer, derselbe Schlüssel",{"id":84,"text":85},"archiv","Dubletten und das Archiv-Flag",{"id":87,"text":88},"ergebnis","Was eine Datenmigration ins CRM am Ende beweisen muss",{"slug":4,"title":5,"subtitle":6,"date":7,"metaTitle":8,"metaDescription":9,"excerpt":10,"readingMinutes":11,"tags":90,"toc":91},[13,14,15,16],[92,93,94,95,96],{"id":19,"text":20},{"id":22,"text":23},{"id":25,"text":26},{"id":28,"text":29},{"id":31,"text":32},1789404874648]