Architecture overview
GreekManage is a multi-tenant SaaS for fraternity and sorority management, built as a Django backend + React SPA with isolated tenant data via Postgres Row-Level Security.
System diagram
Layer responsibilities
Client tier
- React 19 SPA served as static assets from nginx pods
- Capacitor 8 mobile wrapper distributes the same SPA via App Store / Play Store
- Auth via httpOnly cookies (web) and
Authorization: Bearerheader (mobile) - WebSocket upgrade for live AI chatbot streaming and live election results
Edge / ingress
- nginx-ingress terminates TLS via cert-manager + Let's Encrypt
- Path-based routing:
/api,/ws→ backend;/→ frontend - Max upload: 25 MB
- Hostname routing:
app.greekmanage.com,dev.greekmanage.com
Application tier
| Component | Replicas | Concurrency | Notes |
|---|---|---|---|
frontend | 2 | – | Static nginx, read-only rootfs |
backend | 2 | Daphne workers | ASGI for HTTP + WebSocket |
celery | 1+ | 2 per pod | Default queue (most tasks) |
celery-beat | 1 | 1 | Periodic schedule (single instance to avoid double-fires) |
celery-backups | 1 | 2 | Isolated backups queue (long-running, doesn't starve other tasks) |
Data tier
- PostgreSQL 17 with
pgvectorfor AI embeddings - Row-Level Security policies on org-scoped tables — set per request via
OrganizationContextMiddleware→ Multi-tenancy & RLS - Redis 7 for Celery broker, Celery results, Channels pub/sub
- S3 / MinIO for object storage; per-org
StorageConfigallows BYO bucket
External services
- AI: Anthropic Claude (default), OpenAI GPT, Google Gemini, Voyage embeddings; per-org BYOM supported
- Payments: Stripe (most common), plus Braintree, Square, PayPal — per-org config encrypted via
EncryptedTextField - Email: AWS SES, SMTP, SendGrid — platform-level config in
PlatformEmailConfig - SSO: Microsoft 365, Google Workspace, Okta via OAuth 2.0 / OIDC; SAML 2.0 for enterprise
Multi-tenant hierarchy
- A Platform has many Organizations (each tenant is an Organization)
- An Organization can have many Regions (optional grouping)
- An Organization has many Chapters; each chapter belongs to at most one region
- A Membership row joins a
Userto aChapterwith arole(member / officer / president / advisor) andstatus(undergrad / alumni / pnm / etc.)
Module licensing
Per-organization toggles. 9 modules:
Toggling off a module:
- Hides its sidebar items in the frontend (via
<ModuleGuard>) - Returns
403 Module not enabledfrom the backend - Stops its Celery tasks from being scheduled
Request lifecycle (typical authenticated API call)
Backend app inventory
23 Django apps:
| Domain | Apps |
|---|---|
| Core | accounts, authentication, common, organizations, members, platform |
| Engagement | forums, messaging, notifications, events, photos, activity |
| Operations | compliance, elections, finances, retention |
| Programs | learning, foundation, alumni, documents |
| Intelligence | ai_services |
| Platform ops | backups, feedback |
Key cross-cutting modules
| Module | Lives in | What it provides |
|---|---|---|
apps.common.permissions | backend/apps/common/permissions.py | TierPermission base + IsNationalAdmin, IsRegionalAdmin, IsChapterMember, IsChapterOfficer, etc. |
apps.common.middleware | backend/apps/common/middleware.py | OrganizationContextMiddleware (RLS), AuditMiddleware |
apps.common.authentication | backend/apps/common/authentication.py | CookieJWTAuthentication |
apps.authentication.encryption | backend/apps/authentication/encryption.py | Fernet wrappers, rotate_value() for key rotation |
apps.authentication.fields | backend/apps/authentication/fields.py | EncryptedTextField |
Where to go next
- Data model — full ERD + per-table notes
- Multi-tenancy & RLS — how tenant isolation actually works
- Auth & permissions — JWT, SSO, permission classes
- Permission tiers — role hierarchy + decision trees
- Module dependency graph — which modules depend on which
- AI / RAG pipeline — chatbot retrieval flow
- Audit & encryption — what's logged, what's encrypted