Alphazed operates 7+ educational apps (Amal, Thurayya, Qais, KidElite, Alphazed School, Alphazed Montessori, and more) from a single backend codebase and a shared Flutter mobile framework. Each app gets its own database tables (prefixed), configuration, push notifications, email templates, and content — but shares authentication (AWS Cognito), analytics infrastructure, and core learning algorithms.
Backend: Runtime App Selection
How It Works
At deployment, an environment variable selects the app:
# Deploy Amal
export APP_NAME=amal
serverless deploy
# Deploy Thurayya
export APP_NAME=thurayya
serverless deploy
# Deploy Qais
export APP_NAME=qais
serverless deploy
Each deployment creates independent Lambda functions, API Gateway routes, and monitoring—but they all connect to the same backend codebase.
Three-Tier Config Priority
# src/config.py
import os
app_name = os.getenv('APP_NAME', 'amal')
# Tier 1: Exact app match
config = load_json(f'config/{app_name}.json')
# Tier 2: App family match (if exact config doesn't exist)
if not config:
family = app_name.split('_')[0] # 'amal_beta' → 'amal'
config = load_json(f'config/{family}.json')
# Tier 3: Default
if not config:
config = load_json('config/default.json')
Per-App Configuration (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
}
}
Shared vs. Per-App Resources
| Resource | Shared | Per-App | Reason |
|---|---|---|---|
| Lambda code | ✓ Yes | ✗ No | Single codebase, branching by APP_NAME |
| RDS instance | ✓ Yes | ✗ No (tables prefixed) | Cost reduction, single backup |
| S3 content | ✗ No | ✓ Yes | Each app has own curriculum |
| AWS Cognito | ✓ Yes | ✗ No (via app_id) | Central auth, app_id differentiates |
| Analytics lake | ✓ Yes | ✗ No (partitioned by app) | Unified pipeline, segregated data |
| Firebase messaging | ✗ No | ✓ Yes | App-specific APNs + FCM |
Frontend: Flutter Multi-App Architecture
Shared Core (packages/alphazed_common)
- State management (Riverpod)
- Audio handling
- Animation library (Rive integration)
- Design system (colors, typography, widgets)
- Authentication flows
- Analytics client
App-Specific Layers (apps/amal, apps/thurayya, etc.)
apps/
├── amal/
│ ├── lib/
│ │ ├── main.dart (app entry point)
│ │ ├── config/
│ │ │ ├── curriculum.json (Amal's lesson structure)
│ │ │ ├── colors.dart (Amal's theme)
│ │ │ └── characters.json (avatar customization)
│ │ └── screens/ (Amal-specific screens)
│ └── pubspec.yaml (Amal dependencies)
│
├── thurayya/
│ ├── lib/
│ │ ├── main.dart (different entry point)
│ │ ├── config/
│ │ │ ├── curriculum.json (Juz Amma structure)
│ │ │ ├── colors.dart (Thurayya's theme)
│ │ │ └── characters.json (avatar customization)
│ │ └── screens/ (Thurayya-specific screens)
│ └── pubspec.yaml (Thurayya dependencies)
│
└── packages/
└── alphazed_common/ (shared code)
Build-Time Configuration
# Build Amal
flutter build apk --dart-define=APP_NAME=amal --dart-define=CURRICULUM=amal_v3
# Build Thurayya
flutter build apk --dart-define=APP_NAME=thurayya --dart-define=CURRICULUM=thurayya_juzamma
At build time, each app gets its own curriculum data, colors, and configuration baked in. Single code repository, multiple compiled binaries.
Deployment: Independent Stacks
Serverless Framework Configuration
# serverless.yml
service: alphazed-backend
custom:
pythonRequirements:
dockerizePip: true
app_name: ${env:APP_NAME}
functions:
# These functions are deployed for every APP_NAME value
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:
# Each app gets its own CloudWatch log group
${self:custom.app_name}LogGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: /aws/lambda/alphazed-${self:custom.app_name}
RetentionInDays: 30
When you deploy with APP_NAME=amal, CloudFormation creates:
- Lambda functions prefixed
alphazed-amal-* - API Gateway routes under
/amal/* - CloudWatch logs under
/aws/lambda/alphazed-amal - Independent scaling and monitoring
Why This Matters
For Product Teams
- New app launch: weeks instead of months (share infrastructure)
- Feature parity: bug fixes and algorithm improvements apply to all apps instantly
- A/B testing: easily test features on one app before rolling to others
For Engineering
- Single codebase: one set of tests, one CI/CD pipeline
- Shared learning algorithms: spaced repetition and content mixing benefit all apps
- Operational efficiency: one team manages all infrastructure
For Cost
- Shared RDS: fraction of the cost of 7 independent databases
- Shared Cognito: one auth provider for all apps
- Shared analytics: one pipeline serving 7 apps
- Estimated cost savings: $40,000-60,000/year vs. separate backends
Challenges and Solutions
Challenge 1: Database schema conflicts
- Amal needs
amal_user_memorytable - Thurayya needs
thurayya_user_memorytable (different fields for Quran memorization) - Solution: Migrations are app-aware.
migrations/001_amal_user_memory.sqlonly runs whenAPP_NAME=amal
Challenge 2: Different feature sets
- Thurayya has tajweed feedback; Amal doesn't
- Amal has physics games; Thurayya doesn't
- Solution: Feature flags in config (
enable_tajweed_feedback,enable_physics_games)
Challenge 3: Independent scaling
- Amal sees traffic spike; Thurayya is quiet
- Shared Lambda pool means they compete for concurrency
- Solution: CloudWatch scaling policies per app. If
amal-*Lambdas hit concurrency limit, auto-scale independently
FAQ
Q: Doesn't sharing one codebase create coupling between apps?
A: No. Each app's code is in separate directories (apps/amal, apps/thurayya). Shared code is in packages/alphazed_common and explicitly versioned. Tight coupling is a design smell — we catch it in code review.
Q: What if one app needs a breaking API change?
A: We version APIs per app: /amal/v1/*, /thurayya/v1/*. Apps can upgrade independently. Old versions run for 12 months, giving app teams time to update.
Q: Can apps share users? A: Not by default. Each app has its own user table (prefixed). If a parent wants to subscribe to both Amal and Thurayya, they create separate accounts (or we could add a "family" linking feature later).



