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
| Metrik | Wert |
|---|---|
| Backend-Sprache | Go 1.23 |
| Backend-Dienste | Auth, Nutzer, Beiträge, Benachrichtigungen, Analytik, Suche, Upload, WebSocket, Empfehlungen |
| Datenbank / Cache | PostgreSQL 16 · Redis 7 |
| Optionaler Ereignisbus | Kafka |
| Native Clients | Android (Kotlin) · iOS (Swift) · Web (TypeScript) |
| Auth | JWT (Access 15 min, Refresh 7 Tage) · Bcrypt · Rate Limiting |
| Betrieb | Docker 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
- Kontext: Unsere Ventures — Crypton zeigt, wie wir Backend-Verbünde und Clients gemeinsam denken.