Multi-App-Plattform aus einer Codebasis
5 Min. LesezeitMohammad Shaker

Multi-App-Plattform aus einer Codebasis

Alphazed betreibt 7+ Lernapps aus einer Codebasis mit Flutter.

Engineering

Schnelle Antwort

Alphazed betreibt 7+ Lernapps aus einer Codebasis mit Flutter.

Wie wir eine Multi-App-Plattform aus einer Codebasis erstellt haben

Alphazed betreibt über 7 Lernapps (Amal, Thurayya, Qais, KidElite, Alphazed School, Alphazed Montessori und mehr) aus einer einzigen Backend-Codebasis und einem gemeinsamen Flutter-Mobile-Framework. Jede App erhält ihre eigenen Datenbanktabellen (mit Präfix), Konfiguration, Push-Benachrichtigungen, E-Mail-Vorlagen und Inhalte — teilt jedoch die Authentifizierung (AWS Cognito), die Analyseinfrastruktur und die Kernlernalgorithmen.

Backend: App-Auswahl zur Laufzeit

Funktionsweise

Bei der Bereitstellung wählt eine Umgebungsvariable die App aus:

# Bereitstellung Amal
export APP_NAME=amal
serverless deploy

# Bereitstellung Thurayya
export APP_NAME=thurayya
serverless deploy

# Bereitstellung Qais
export APP_NAME=qais
serverless deploy

Jede Bereitstellung erstellt unabhängige Lambda-Funktionen, API Gateway-Routen und Überwachungen, aber sie verbinden sich alle mit derselben Backend-Codebasis.

Drei-Stufen-Konfigurationspriorität

# src/config.py
import os

app_name = os.getenv('APP_NAME', 'amal')

# Stufe 1: Exakte App-Übereinstimmung
config = load_json(f'config/{app_name}.json')

# Stufe 2: App-Familien-Übereinstimmung (wenn keine exakte Konfiguration vorhanden ist)
if not config:
    family = app_name.split('_')[0]  # 'amal_beta' → 'amal'
    config = load_json(f'config/{family}.json')

# Stufe 3: Standard
if not config:
    config = load_json('config/default.json')

App-spezifische Konfiguration (config/amal.json)

{
  "app_name": "amal",
  "app_id": "com.alphazed.amal",
  "database": {
    "table_prefix": "amal_"
  },
  "email": {
    "template_dir": "templates/amal",
    "from_address": "amal@alphazed.com",
    "from_name": "Amal Team"
  },
  "push_notifications": {
    "firebase_project": "alphazed-amal",
    "apns_certificate": "certs/amal.pem"
  },
  "content": {
    "s3_bucket": "amal-content-production",
    "curriculum_id": "amal_v3_arabic"
  },
  "feature_flags": {
    "enable_tajweed_feedback": false,
    "enable_noorani_qaida": false,
    "enable_juz_amma": false,
    "enable_creature_building": true,
    "enable_physics_games": true
  },
  "pricing": {
    "monthly_usd": 6.99,
    "yearly_usd": 67.99,
    "trial_days": 14
  }
}

Geteilte vs. App-spezifische Ressourcen

Ressource Geteilt App-spezifisch Grund
Lambda-Code ✓ Ja ✗ Nein Eine Codebasis, Zweige durch APP_NAME
RDS-Instanz ✓ Ja ✗ Nein (Tabellen mit Präfix) Kostensenkung, ein Backup
S3-Inhalte ✗ Nein ✓ Ja Jede App hat einen eigenen Lehrplan
AWS Cognito ✓ Ja ✗ Nein (über app_id) Zentrale Authentifizierung, app_id differenziert
Analytics-See ✓ Ja ✗ Nein (partitioniert nach App) Einheitliche Pipeline, getrennte Daten
Firebase-Messaging ✗ Nein ✓ Ja App-spezifische APNs + FCM

Frontend: Flutter Multi-App-Architektur

Geteilter Kern (packages/alphazed_common)

  • Zustandsverwaltung (Riverpod)
  • Audioverarbeitung
  • Animationsbibliothek (Rive-Integration)
  • Designsyst...client

App-spezifische Schichten (apps/amal, apps/thurayya, etc.)

apps/
  ├── amal/
  │   ├── lib/
  │   │   ├── main.dart (App-Einstiegspunkt)
  │   │   ├── config/
  │   │   │   ├── curriculum.json (Amals Lektionenstruktur)
  │   │   │   ├── colors.dart (Amals Thema)
  │   │   │   └── characters.json (Avatar-Anpassung)
  │   │   └── screens/ (Amal-spezifische Bildschirme)
  │   └── pubspec.yaml (Amal-Abhängigkeiten)
  │
  ├── thurayya/
  │   ├── lib/
  │   │   ├── main.dart (anderer Einstiegspunkt)
  │   │   ├── config/
  │   │   │   ├── curriculum.json (Juz Amma Struktur)
  │   │   │   ├── colors.dart (Thurayyas Thema)
  │   │   │   └── characters.json (Avatar-Anpassung)
  │   │   └── screens/ (Thurayya-spezifische Bildschirme)
  │   └── pubspec.yaml (Thurayya-Abhängigkeiten)
  │
  └── packages/
      └── alphazed_common/ (geteilter Code)

Build-Zeit-Konfiguration

# Erstelle Amal
flutter build apk --dart-define=APP_NAME=amal --dart-define=CURRICULUM=amal_v3

# Erstelle Thurayya
flutter build apk --dart-define=APP_NAME=thurayya --dart-define=CURRICULUM=thurayya_juzamma

Zur Build-Zeit erhält jede App ihre eigenen Lehrplandaten, Farben und die Konfiguration. Einzelnes Code-Repository, mehrere kompilierte Binärdateien.

Bereitstellung: Unabhängige Stacks

Serverless-Framework-Konfiguration

# serverless.yml
service: alphazed-backend

custom:
  pythonRequirements:
    dockerizePip: true
  app_name: ${env:APP_NAME}

functions:
  # Diese Funktionen werden für jeden APP_NAME-Wert bereitgestellt
  get_user:
    handler: src/handlers/user.get_user
    events:
      - http:
          path: app/{app_name}/user/{user_id}
          method: get
  
  content_duo:
    handler: src/handlers/content.generate_content_duo
    timeout: 20
    events:
      - http:
          path: app/{app_name}/content_duo
          method: post

resources:
  Resources:
    # Jede App erhält ihre eigene CloudWatch-Protokollgruppe
    ${self:custom.app_name}LogGroup:
      Type: AWS::Logs::LogGroup
      Properties:
        LogGroupName: /aws/lambda/alphazed-${self:custom.app_name}
        RetentionInDays: 30

Wenn Sie mit APP_NAME=amal bereitstellen, erstellt CloudFormation:

  • Lambda-Funktionen mit Präfix alphazed-amal-*
  • API Gateway-Routen unter /amal/*
  • CloudWatch-Protokolle unter /aws/lambda/alphazed-amal
  • Unabhängige Skalierung und Überwachung

Warum das wichtig ist

Für Produktteams

  • Neue App-Einführung: Wochen statt Monate (gemeinsame Infrastruktur)
  • Funktionsparität: Fehlerbehebungen und Algorithmusverbesserungen gelten sofort für alle Apps
  • A/B-Tests: Eigenschaften können einfach in einer App getestet werden, bevor sie auf andere ausgeweitet werden

Für die Technik

  • Einzige Codebasis: ein Testset, eine CI/CD-Pipeline
  • Geteilte Lernalgorithmen: Alle Apps profitieren von Abstandsrepetition und Inhaltemischung
  • Betriebseffizienz: Ein Team verwaltet die gesamte Infrastruktur

Für die Kosten

  • Gemeinsames RDS: Bruchteil der Kosten von 7 unabhängigen Datenbanken
  • Gemeinsames Cognito: ein Authentifizierungsanbieter für alle Apps
  • Gemeinsame Analyse: eine Pipeline, die 7 Apps bedient
  • Geschätzte Kosteneinsparungen: $40.000-60.000/Jahr im Vergleich zu separaten Backends

Herausforderungen und Lösungen

Herausforderung 1: Konflikte im Datenbankschema

  • Amal benötigt amal_user_memory-Tabelle
  • Thurayya benötigt thurayya_user_memory-Tabelle (unterschiedliche Felder für Koran-Memorisation)
  • Lösung: Migrationen sind App-spezifisch. migrations/001_amal_user_memory.sql werden nur ausgeführt, wenn APP_NAME=amal

Herausforderung 2: Unterschiedliche Funktionssätze

  • Thurayya hat Tajweed-Feedback; Amal nicht
  • Amal hat Physikspiele; Thurayya nicht
  • Lösung: Funktionsflags in der Konfiguration (enable_tajweed_feedback, enable_physics_games)

Herausforderung 3: Unabhängige Skalierung

  • Amal sieht Traffic-Spitze; Thurayya ist ruhig
  • Gemeinsamer Lambda-Pool bedeutet, dass sie um Gleichzeitigkeit konkurrieren
  • Lösung: CloudWatch-Skalierungsrichtlinien pro App. Wenn amal-* Lambdas das Gleichzeitigkeitlimit überschreiten, automatisch unabhängig skalieren

FAQ

F: Führt die gemeinsame Nutzung einer einzigen Codebasis nicht zur Koppelung zwischen Apps? A: Nein. Der Code jeder App befindet sich in separaten Verzeichnissen (apps/amal, apps/thurayya). Gemeinsamer Code befindet sich in packages/alphazed_common und ist explizit versioniert. Eine enge Kopplung ist ein Designgeruch — wir fangen ihn bei der Codeüberprüfung ab.

F: Was passiert, wenn eine App eine breaking API-Änderung benötigt? A: Wir versionieren APIs pro App: /amal/v1/*, /thurayya/v1/*. Apps können unabhängig aufrüsten. Alte Versionen laufen 12 Monate lang, was den App-Teams Zeit zum Aktualisieren gibt.

F: Können Apps Benutzer teilen? A: Nicht standardmäßig. Jede App hat ihre eigene Benutzertabelle (mit Präfix). Wenn ein Elternteil sowohl Amal als auch Thurayya abonnieren möchte, erstellt er separate Konten (oder wir könnten später eine „Familien“-Verknüpfungsfunktion hinzufügen).

Verwandte Artikel