Zum Inhalt springen

Fallstudie

Eine soziale Plattform als Dienste-Verbund

Crypton umfasst Authentifizierung, Feed, Beiträge, Benachrichtigungen, Suche, Upload und Echtzeit-Kommunikation als eigenständige Dienste hinter einem einheitlichen API.

Herausforderung

Eine soziale Plattform sieht von aussen einheitlich aus — Feed, Beiträge, Nachrichten, Benachrichtigungen — aber die dahinterliegenden Anforderungen sind sehr unterschiedlich. Authentifizierung braucht harte Fristen und Ratenbegrenzung, ein Nachrichten-Kanal braucht persistente WebSocket-Verbindungen, ein Feed braucht Caching und Empfehlungen, Datei-Uploads brauchen ganz andere Grössenordnungen als Text.

Wird das alles in ein einziges Backend gepresst, teilen sich Prozesse Ressourcen, die eigentlich getrennt skaliert werden müssten. Ein spikeender Upload-Endpunkt kann dann den Login-Pfad ausbremsen; eine langsame Suche blockiert Benachrichtigungen.

Ziel für Crypton war deshalb ein Backend-Verbund mit klaren Grenzen zwischen den Diensten, einheitlichem Auth-Modell an der Kante und einem gemeinsamen Deploy-Ablauf über Docker Compose — bei gleichzeitiger Konsolidierung nativer Clients auf iOS, Android und Web.

Ansatz

Fünf Grundsätze:

  • Dienste nach Fachlichkeit trennen — Auth, Nutzer, Beiträge, Suche, Upload, Benachrichtigungen, WebSocket, Empfehlungen und Analytik jeweils als eigener Dienst mit eigener Datenverantwortung.
  • Eine Sprache im Backend — Go 1.23 für alle Dienste, damit Muster, Bibliotheken und Betriebs-Know-how geteilt werden können.
  • Zwei Datenstore-Kategorien — PostgreSQL für dauerhafte Daten, Redis für Cache, Sessions und Pub/Sub.
  • Sicherheit in der Basis — JWT mit Access- und Refresh-Tokens, Rate Limiting getrennt für Auth und API, Security-Header, CORS-Whitelist, alles im Code und nicht erst in nginx.
  • Betrieb per Docker Compose — Health Checks, persistente Volumes, klare Startreihenfolge, damit lokale Entwicklung und Produktion demselben Ablauf folgen.

Was wir gebaut haben

Backend-Dienste (Go)

Ein Verbund von Go-1.23-Diensten unter backend/ und microservices/: Authentifizierung, Nutzerverwaltung, Beiträge, Benachrichtigungen, Analytik, Suche, Upload, WebSocket-Server, Empfehlungen. Jeder Dienst hat eigene Endpunkte und schreibt in sein eigenes Schema.

Datenbank & Cache

PostgreSQL 16 mit UUID-Unterstützung als Kern-Datenbank (database/, init-db.sql), Redis 7 für Caching, Sessions und Pub/Sub. Seed- und Migrationsskripte (seed-data.sql) machen einen frischen Aufsatz reproduzierbar.

Android-Client (Kotlin)

android-app/ enthält den nativen Android-Client mit geteilten Kotlin-Modulen (shared-kotlin/). Der Client spricht dieselben Backend-APIs wie die anderen Oberflächen.

iOS-Client (Swift)

ios-app/ liefert den nativen iOS-Client. Zusammen mit dem Android-Client teilt er sich Datenmodelle über OpenAPI-generierte SDKs (sdk/, sdks/).

Web-Oberfläche und Werkzeuge

TypeScript-Anteile in apps/, frontend-integration/, sdk/ und packages/ liefern Web-Oberfläche, geteilte Typen und Werkzeuge (Vite-basiert).

Sicherheit

security/, nginx.conf, nginx/, CSRF- und 2FA-Guides sowie Skripte für Token-Blacklist-Tests (test_token_blacklist.sh, test_csrf_protection.sh) bündeln die Sicherheitsarbeit. JWT-Access-Token (15 min), Refresh-Token (7 Tage), Bcrypt für Passwörter, Rate Limiting je nach Route.

Betrieb & Beobachtbarkeit

docker-compose.production.yml, docker-compose.microservices.yml, monitoring/, k8s/, jaeger/, kafka/, kong/, consul/ — der Verbund lässt sich sowohl in einer schlanken lokalen Compose-Umgebung als auch mit vollständiger Beobachtungs-Kette starten.

Werkzeug-Skripte

Zahlreiche test-*.sh- und docker-*.sh-Skripte im Wurzelverzeichnis unterstützen Entwickler:innen bei Standard-Aufgaben (API-Test, Container-Start/-Stopp, Backup/Restore).

Architektur

Crypton ist ein Dienste-Verbund in Go: mehrere Backend-Dienste (u. a. Auth, Nutzer, Beiträge, Benachrichtigungen, Analytik, Suche, Upload, WebSocket, Empfehlungen) laufen als getrennte Container hinter einem gemeinsamen Eingangspunkt. Ein API-Gateway (in fortgeschrittenen Setups Kong) routet Anfragen an den zuständigen Dienst.

Die Datenschicht teilt sich in PostgreSQL 16 für zustandsbehaftete Domänendaten und Redis 7 für Cache, Sessions und Pub/Sub. Wo Ereignisse zwischen Diensten fliessen sollen (Nachrichten, Benachrichtigungen), gibt es Kafka als optionalen Bus (kafka/).

Auf der Client-Seite laufen drei native Oberflächen — Android (Kotlin), iOS (Swift) und Web (TypeScript) — gegen dieselben APIs. Geteilte Datenmodelle werden über SDKs unter sdk/, sdks/ und shared-kotlin/ synchron gehalten, damit ein Änderungswunsch am Beitragsschema nicht drei Mal einzeln umgesetzt werden muss.

Betrieben wird der Verbund per Docker Compose in mehreren Profilen: von docker-compose.simple.yml für die lokale Entwicklung bis docker-compose.production.yml mit vollständiger Beobachtungs-Kette (Prometheus, Jaeger, Consul). Health Checks und persistente Volumes gehören zum Standard-Setup.

Zahlen & Fakten

MetrikWert
Backend-SpracheGo 1.23
Backend-DiensteAuth, Nutzer, Beiträge, Benachrichtigungen, Analytik, Suche, Upload, WebSocket, Empfehlungen
Datenbank / CachePostgreSQL 16 · Redis 7
Optionaler EreignisbusKafka
Native ClientsAndroid (Kotlin) · iOS (Swift) · Web (TypeScript)
AuthJWT (Access 15 min, Refresh 7 Tage) · Bcrypt · Rate Limiting
BetriebDocker Compose (mehrere Profile) · Health Checks · Prometheus · Jaeger

Was wir gelernt haben

Ein Dienste-Verbund zwingt zu klaren Datenverantwortlichkeiten. Sobald jeder Dienst sein eigenes Schema besitzt, sind versteckte SQL-Joins über Domänengrenzen hinweg keine Option mehr. Das kostet in der Modellierung Zeit, macht aber jede Änderung nachvollziehbar und lokal ausrollbar.

Native Clients mit generierten SDKs skalieren besser als ein „Universal-Client”. Der Aufwand, gemeinsame Typen aus dem Backend zu generieren und in Kotlin, Swift und TypeScript zu verteilen, ist geringer als der Aufwand, ein einziges plattformübergreifendes Framework zu pflegen und dessen Grenzen ständig zu umgehen.

Sicherheit im Code, nicht am Reverse-Proxy. Rate Limiting, JWT-Prüfung und CSRF-Absicherung leben in den Diensten selbst. Das macht sie im Test verifizierbar und schützt vor Regressionen, wenn die nginx-Konfiguration einmal geändert wird.

Nächste Schritte

  • Konsolidierung der Docker-Compose-Profile: weniger Varianten, klarere Rollen (dev, staging, production).
  • Ausbau der Beobachtungs-Kette in Standard-Deploys (Prometheus + Jaeger als Default, nicht optional).
  • SDK-Generierung strenger an OpenAPI koppeln, damit alle drei Clients immer denselben Vertragsstand kennen.

Verwandt

Zusammenarbeit

Ähnliche Arbeit im Sinn?

Lassen Sie uns kurz sprechen — kein Verkaufsgespräch.