DjangoPlay — Architecture Style
DjangoPlay is structured as a modular monolith built on Django and Django REST Framework.
On this page ▾
1. Overview
The application combines:
- Domain-oriented Django apps
- Layered application architecture
- Service-oriented business logic
- Centralized authorization
- External identity through AuthX
- Auditability
- Asynchronous processing with Celery
- Redis-backed infrastructure
- Dedicated integration boundaries
- Versioned REST APIs
The architecture is intentionally modular without introducing microservices prematurely.
The primary goal is to keep domain functionality isolated and maintainable while allowing infrastructure, integrations, and individual application modules to evolve independently.
2. Architecture Classification
| Category | Architecture Style |
|---|---|
| System Architecture | Modular Monolith |
| Application Architecture | Layered Architecture |
| Domain Structure | Domain-Oriented Django Apps |
| Business Logic | Service Layer |
| Data Access | Django ORM / Query Services |
| Authorization | Policy-Based Access Control |
| Identity | External AuthX Identity Service |
| API | Django REST Framework |
| API Evolution | URL-Based API Versioning |
| Background Processing | Celery |
| Broker / Cache | Redis |
| Persistence | PostgreSQL |
| External Services | Dedicated Integration Boundaries |
| Auditability | Centralized Audit Module |
| Deployment | Nginx + Gunicorn + Celery |
| Static Assets | Local Static Serving / Cloudflare R2 + CDN |
| Issue Tracking | Generic Issue Tracker Integration |
3. Modular Monolith
DjangoPlay uses a modular monolith rather than a collection of independent microservices.
Multiple domain modules run inside the same Django application and share the application's deployment and primary PostgreSQL database.
The current application contains domain and infrastructure modules such as:
webapp/
├── aicore
├── apidocs
├── audit
├── core
├── entities
├── finance
├── frontend
├── helpdesk
├── industries
├── locations
├── mailer
├── paystream
├── policyengine
├── teamcentral
├── users
│
└── integrations/
└── issuetracker/
`The exact set of applications may evolve as DjangoPlay develops.
The important architectural rule is that each application represents a meaningful responsibility or domain rather than being an arbitrary collection of unrelated functionality.
4. Domain-Oriented Application Structure
Each Django application owns a defined area of responsibility.
Examples include:
| Application | Responsibility |
|---|---|
users |
User accounts, authentication flows, signup and verification |
teamcentral |
Teams, organizational structure and related access context |
policyengine |
Role-based authorization and policy evaluation |
audit |
Platform-wide audit trail |
entities |
Business/entity records |
locations |
Geographic reference data |
industries |
Industry and classification reference data |
finance |
Financial domain functionality |
helpdesk |
Support workflows and issue/report handling |
mailer |
Transactional email functionality |
aicore |
In-app AI assistant and provider orchestration |
apidocs |
API documentation and developer-facing API support |
frontend |
Templates, static assets and presentation-layer functionality |
core |
Cross-cutting application infrastructure |
paystream |
Project package, settings, security and integration wiring |
The application boundaries are logical boundaries inside the monolith.
They are not necessarily separate deployable services.
5. Layered Application Architecture
DjangoPlay separates request handling, application workflows, domain state, and infrastructure concerns.
Incoming Request
│
▼
Middleware / Context
│
▼
URL Routing
│
┌────────────┴────────────┐
▼ ▼
Django Web Views DRF APIs
│ │
└────────────┬────────────┘
▼
Service Layer
│
┌─────────────┼─────────────┐
▼ ▼ ▼
Policies Models Tasks
│ │ │
│ ▼ ▼
│ PostgreSQL Redis
│
└─────────────┬─────────────┐
▼ ▼
Audit IntegrationsThe architecture intentionally keeps core business workflows out of the presentation layer.
6. Presentation Layer
The presentation layer is responsible for interacting with clients.
It includes:
- Django web views
- DRF API views and ViewSets
- Templates
- Serializers
- Presentation-specific request/response handling
The presentation layer should:
- Receive requests
- Validate request structure
- Resolve the appropriate service
- Return responses
- Handle presentation-specific concerns
It should not become the primary location for business workflows.
Typical flow:
HTTP Request
│
▼
View / API View
│
▼
Serializer
│
▼
Service
│
▼
Response7. Service Layer
The service layer is the primary location for application and business workflows.
Services coordinate:
- Business rules
- Transactions
- Domain workflows
- Model operations
- Authorization checks
- External integrations
- Background task dispatch
- Notifications
- Audit operations
Typical flow:
View / API
│
▼
Service
│
├── Policy
├── Model / Query
├── Audit
├── Celery Task
└── IntegrationServices provide a stable application boundary so that the same business operation can be reused by different entry points.
For example, a workflow should not need to be duplicated because it is invoked from both a Django web view and an API endpoint.
8. Domain and Data Layer
Django models represent persistent domain state and relationships.
The domain/data layer contains:
- Django models
- Relationships
- Persistence-facing state
- Model-level validation appropriate to the domain
- Domain-specific state transitions where appropriate
Complex application workflows should remain in services rather than becoming embedded inside model methods.
Database access is primarily provided through the Django ORM.
Where queries become complex or reusable, query/selector services can isolate that logic from views and workflows.
9. Query and Selector Pattern
Complex or reusable data retrieval should be isolated from presentation code.
Typical responsibilities include:
- Filtering
- Search
- Ordering
- Related-object loading
- Query optimization
- Reusable domain queries
Conceptually:
Service
│
▼
Query / Selector
│
▼
Django ORM
│
▼
PostgreSQLThis prevents large query expressions from becoming scattered throughout views and other application components.
10. Authorization Architecture
Authorization is treated as a cross-cutting concern rather than being implemented independently in every view.
DjangoPlay uses the policyengine application for centralized authorization
logic.
Policies can evaluate application context such as:
- User roles
- Ownership
- Organizational context
- Allowed actions
- Resource access
- Role-based permissions
Typical flow:
Request
│
▼
Authentication
│
▼
Policy Evaluation
│
├── Allowed ──► Application Service
│
└── Denied ──► Access DeniedAuthorization should be enforced at the appropriate application boundary rather than relying solely on presentation-layer checks.
11. Identity Architecture
DjangoPlay uses AuthX as its external identity service.
Identity responsibilities are deliberately separated from DjangoPlay's domain/application responsibilities.
AuthX provides the identity authority for authentication flows such as:
- Login
- Signup
- Password reset
- Identity verification
- SSO
The architectural boundary is:
┌──────────────────┐
│ AuthX │
│ Identity Service │
└────────┬─────────┘
│
Identity / JWT
│
▼
┌──────────────────┐
│ DjangoPlay │
│ Application │
└──────────────────┘AuthX is the JWT signing authority for the AuthX identity integration.
DjangoPlay verifies AuthX-issued identity tokens rather than owning the AuthX private signing key.
This separation protects the identity boundary and keeps authentication infrastructure independent from application-domain logic.
12. Audit Architecture
Auditability is a platform-level concern.
The audit application provides centralized audit logging for meaningful
system actions and state changes.
Typical events include:
- Authentication-related events
- Administrative actions
- Create operations
- Update operations
- Delete operations
- State transitions
- Important system operations
Conceptually:
Application Service
│
▼
Audit Service
│
▼
Audit Log
│
▼
PostgreSQLAudit operations should remain attributable to the actor or system process responsible for the change.
13. Background Processing
DjangoPlay uses Celery for asynchronous and long-running work.
Redis provides the supporting broker/cache infrastructure.
Typical flow:
Application Service
│
▼
Celery Task
│
▼
Redis
│
▼
Celery Worker
│
▼
External Service / Database / File OperationBackground processing is appropriate for operations such as:
- Transactional email
- External API calls
- File processing
- Long-running operations
- Scheduled maintenance
- Synchronization workflows
The request/response path should not unnecessarily perform long-running work that belongs in the background processing layer.
14. Integration Architecture
External systems are accessed through explicit integration boundaries.
The application should not scatter third-party API calls throughout domain views or models.
Conceptually:
DjangoPlay Service
│
▼
Integration Boundary
│
▼
External ServiceThis architecture allows external providers to be replaced or modified without restructuring the application's core domain workflows.
Current integration categories include:
- AuthX Identity
- Generic Issue Tracker
- Email / SMTP providers
- AI providers
- Cloudflare R2
- Other external APIs
15. Generic Issue Tracker Integration
DjangoPlay integrates with the reusable Generic Issue Tracker package rather than maintaining an isolated issue-tracking implementation inside the host application.
The integration is located under:
paystream/integrations/issuetracker/The reusable package provides issue-management capabilities while DjangoPlay provides the host-specific integration, access control, and application workflows.
Conceptually:
DjangoPlay
│
▼
Helpdesk / Application Workflows
│
▼
DjangoPlay Issue Tracker Integration
│
▼
Generic Issue Tracker
│
├── Issues
├── Comments
├── Attachments
├── Labels
└── Status HistoryThis keeps the issue-tracking capability reusable while allowing DjangoPlay to apply its own application-level policies and workflows.
The helpdesk application acts as an important host-side integration point
for bug reports, support tickets, and issue-tracker workflows.
16. Email Architecture
Email delivery is isolated from individual business modules through the mailer infrastructure.
Typical flow:
Application Service
│
▼
Mailer
│
▼
Celery Task
│
▼
SMTP / ProviderThis prevents individual applications from implementing SMTP or provider communication independently.
Email configuration and provider credentials are maintained separately from business-domain logic.
17. AI Integration Architecture
The aicore application provides the in-app AI assistant and acts as the
application boundary for AI provider communication.
The provider implementation is intentionally replaceable.
Conceptually:
Authenticated User
│
▼
aicore
│
▼
Provider Registry
│
┌────┼───────────────┐
▼ ▼ ▼
xAI OpenAI Custom Providers
│
Ollama / vLLM / ...AI provider credentials and provider-specific configuration remain outside domain application logic.
The architecture supports changing providers without changing the rest of the application workflow.
Detailed AI architecture belongs in the dedicated aicore documentation
rather than this system architecture document.
18. API Architecture
DjangoPlay exposes REST APIs through Django REST Framework.
API endpoints are organized using explicit URL namespaces.
Typical structure:
/api/v1/
│
├── users/
├── issues/
├── ...
│
└── ...API endpoints follow the same application architecture as web requests:
DRF View / ViewSet
│
▼
Serializer
│
▼
Service
│
▼
Domain / IntegrationAPI presentation code should not duplicate business workflows that already exist in the service layer.
19. API Versioning
DjangoPlay uses URL-based API versioning to allow controlled API evolution.
For example:
/api/v1/
/api/v2/A version may provide its own:
- URL configuration
- Views
- Serializers
- Version-specific presentation behavior
The underlying business services can remain shared where the business semantics are unchanged.
Conceptually:
Client
│
┌────────┴────────┐
▼ ▼
/api/v1/ /api/v2/
│ │
v1 Views v2 Views
│ │
v1 Serializers v2 Serializers
│ │
└────────┬────────┘
▼
Services
│
▼
Domain DataThis separates API compatibility concerns from the core application domain.
20. Cross-Cutting Infrastructure
Several concerns span multiple Django applications.
These are treated as platform infrastructure rather than duplicated inside individual domains.
Examples include:
| Concern | Primary Component |
|---|---|
| Identity | AuthX integration / users |
| Authorization | policyengine |
| Auditability | audit |
mailer |
|
| Async processing | Celery |
| Cache / broker | Redis |
| Application infrastructure | core / paystream |
| API documentation | apidocs |
| External service boundaries | integrations |
Cross-cutting infrastructure should remain independent of individual domain workflows wherever practical.
21. Infrastructure Architecture
The current runtime is designed as a conventional Django production stack.
Client
│
▼
Nginx
│
▼
Gunicorn
│
▼
Django Application
│
┌─────────────┼─────────────┐
▼ ▼ ▼
PostgreSQL Redis Celery
│ │ │
│ │ ▼
│ │ Background
│ │ Workers
│ │
└─────────────┴─────────────┘External services connect through explicit application boundaries.
Examples include:
DjangoPlay ──► AuthX
DjangoPlay ──► SMTP / Email Provider
DjangoPlay ──► AI Providers
DjangoPlay ──► Cloudflare R2
DjangoPlay ──► Generic Issue Tracker
DjangoPlay ──► External APIs22. Static Assets and CDN
Frontend assets are built by the DjangoPlay frontend packaging workflow.
Depending on the environment, assets may be served locally or through the Cloudflare R2/CDN path.
Conceptually:
Frontend Source
│
▼
Asset Build / Packaging
│
├──────────────► Local Static Serving
│
└──────────────► Cloudflare R2
│
▼
CDNThe CDN path is an infrastructure concern and does not change the Django application architecture.
23. Dependency Direction
DjangoPlay follows a general dependency direction:
Presentation
│
▼
Application Services
│
├──────► Policies
│
├──────► Domain Models / Queries
│
├──────► Audit
│
├──────► Tasks
│
└──────► IntegrationsThe preferred direction is from application entry points toward reusable application/domain components.
Domain modules should avoid unnecessary dependencies on presentation components.
For cross-domain communication, application services and explicit integration boundaries are preferred over direct coupling wherever practical.
24. Events and Signals
Django signals are used for event-oriented behavior where appropriate.
Signals are useful for:
- Audit events
- Related state updates
- Notifications
- Event propagation
- Background task triggering
Signals should remain lightweight.
Heavy workflows should be delegated to services or background tasks.
Preferred pattern:
Signal
│
▼
Service / Task
│
▼
Business OperationRather than:
Signal
│
└── Large Business WorkflowThis keeps event handling predictable and testable.
25. Application Boundary Rules
The following architectural rules apply across DjangoPlay.
Views
Views should handle HTTP concerns and delegate application behavior.
Serializers
Serializers should handle request/response representation and validation, not become the primary business-logic layer.
Services
Services own application workflows and business operations.
Models
Models represent domain state and persistence relationships.
Policies
Authorization decisions belong to the policy layer.
Tasks
Long-running or asynchronous work belongs in Celery tasks.
Integrations
External-system communication belongs behind integration boundaries.
Signals
Signals should remain lightweight and delegate substantial work.
26. Architecture Principles
DjangoPlay follows these core principles:
| Principle | Meaning |
|---|---|
| Modular Monolith | Keep domains modular without premature service decomposition |
| Domain Ownership | Each application owns a meaningful responsibility |
| Service First | Business workflows live in services |
| Thin Presentation | Views and serializers remain focused on transport concerns |
| Centralized Authorization | Access decisions use shared policy mechanisms |
| Protected Identity Boundary | AuthX remains the external identity authority |
| Auditability | Important state changes remain attributable and observable |
| Explicit Integrations | External systems are isolated behind integration boundaries |
| Async by Design | Long-running work is delegated to Celery |
| Reusable Infrastructure | Shared concerns are implemented once where practical |
| API Stability | API evolution uses explicit versioning |
| Separation of Concerns | Presentation, application, domain and infrastructure responsibilities remain distinct |
| Replaceable Dependencies | External providers should not dictate domain architecture |
27. Why Modular Monolith Instead of Microservices?
DjangoPlay intentionally does not split every domain into a separate service.
A modular monolith provides:
- Clear domain boundaries
- One deployment unit
- Simpler local development
- Simpler transactions
- Lower operational overhead
- Easier debugging
- Shared infrastructure
- Reusable application services
The architecture nevertheless keeps boundaries explicit enough that a future domain can be extracted into a separate service if there is a genuine operational or scaling reason.
The goal is therefore:
Strong internal boundaries
+
Simple deployment
+
Optional future extractionrather than introducing distributed-system complexity prematurely.
28. Evolution and Scalability
The architecture supports scaling in several dimensions.
Application Scaling
The Django application can be scaled vertically or horizontally behind a load balancer.
Worker Scaling
Celery workers can be scaled independently from web processes.
Database Scaling
PostgreSQL can be optimized or scaled independently as application demand increases.
Cache Scaling
Redis can be expanded or separated according to workload requirements.
Integration Scaling
External integrations remain isolated so that individual providers can be changed or scaled without restructuring domain applications.
The current architecture therefore provides a path from a single-server deployment toward a larger multi-instance deployment without requiring an immediate architectural rewrite.
29. Architecture Summary
DjangoPlay is a modular Django monolith with layered application design.
Its architectural structure can be summarized as:
DJANGOPLAY
│
┌─────────┴─────────┐
│ │
Presentation REST APIs
│ │
└─────────┬─────────┘
▼
Service Layer
│
┌────────────────┼────────────────┐
▼ ▼ ▼
Policies Domain Apps Integrations
│ │ │
│ ▼ ▼
│ PostgreSQL External Services
│
├──────────────► Audit
│
└──────────────► Celery
│
▼
RedisThe resulting architecture keeps DjangoPlay deployable as a single application while maintaining explicit boundaries between:
- Identity
- Authorization
- Domain applications
- Business workflows
- Persistence
- Auditability
- Background processing
- External integrations
- Infrastructure
This provides a practical foundation for continued development while preserving a clear path for future scaling and domain extraction.