Skip to main content

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: Bearer header (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

ComponentReplicasConcurrencyNotes
frontend2Static nginx, read-only rootfs
backend2Daphne workersASGI for HTTP + WebSocket
celery1+2 per podDefault queue (most tasks)
celery-beat11Periodic schedule (single instance to avoid double-fires)
celery-backups12Isolated backups queue (long-running, doesn't starve other tasks)

Data tier

  • PostgreSQL 17 with pgvector for AI embeddings
  • Row-Level Security policies on org-scoped tables — set per request via OrganizationContextMiddlewareMulti-tenancy & RLS
  • Redis 7 for Celery broker, Celery results, Channels pub/sub
  • S3 / MinIO for object storage; per-org StorageConfig allows 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 User to a Chapter with a role (member / officer / president / advisor) and status (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 enabled from the backend
  • Stops its Celery tasks from being scheduled

Module dependency graph

Request lifecycle (typical authenticated API call)

Backend app inventory

23 Django apps:

DomainApps
Coreaccounts, authentication, common, organizations, members, platform
Engagementforums, messaging, notifications, events, photos, activity
Operationscompliance, elections, finances, retention
Programslearning, foundation, alumni, documents
Intelligenceai_services
Platform opsbackups, feedback

Per-app deep dive

Key cross-cutting modules

ModuleLives inWhat it provides
apps.common.permissionsbackend/apps/common/permissions.pyTierPermission base + IsNationalAdmin, IsRegionalAdmin, IsChapterMember, IsChapterOfficer, etc.
apps.common.middlewarebackend/apps/common/middleware.pyOrganizationContextMiddleware (RLS), AuditMiddleware
apps.common.authenticationbackend/apps/common/authentication.pyCookieJWTAuthentication
apps.authentication.encryptionbackend/apps/authentication/encryption.pyFernet wrappers, rotate_value() for key rotation
apps.authentication.fieldsbackend/apps/authentication/fields.pyEncryptedTextField

Where to go next