Feature flags & module enablement (Reference)
This page explains what can be enabled/disabled without code changes across the entire platform.
1) Module enablement (verticals)
The platform supports enabling/disabling major modules ("verticals") independently:
| Module | Description | Key functionality |
|---|---|---|
| Occurrences | Citizen issue reporting | Submit, triage, workflow, SLAs |
| Equipment | Asset management | Inventory, maintenance, inspections, reservations |
| Occupancy | Public space monitoring | Sensors, POIs, live dashboards, alerts |
How module enablement works
Modules are enabled via the ENABLED_MODULES setting:
ENABLED_MODULES = ['occurrences', 'equipment', 'occupancy']
When a module is disabled: - Its API routes are not registered - Admin sidebar links are hidden - Related functionality is not accessible - Other modules continue to work independently
Module dependencies
Some modules have soft dependencies: - Occupancy can optionally integrate with Equipment for sensor asset management - If Equipment is disabled, Occupancy works standalone
Checking module status
Behind the scenes:
- Module checks: apps/utils/module_registry.py → is_module_enabled()
- API routes: Registered conditionally in config/api_router.py
- Admin visibility: Controlled via Unfold admin configuration
2) Occurrences module flags
Within the Occurrences module, workflow features can be toggled using environment variables.
These are collected into OCCURRENCES_WORKFLOW_FEATURES in config/settings/base.py.
Available flags
| Flag | Default | Description |
|---|---|---|
OCCURRENCES_ENABLE_TEMPLATES |
True | Response templates for staff |
OCCURRENCES_ENABLE_CUSTOM_STATES |
True | Custom workflow states |
OCCURRENCES_ENABLE_SLA_TRACKING |
True | Priority-based SLA deadlines |
OCCURRENCES_ENABLE_ESCALATIONS |
False | SLA breach notifications |
OCCURRENCES_ENABLE_ROUTING |
False | External system routing |
OCCURRENCES_ENABLE_DUPLICATE_DETECTION |
True | Similar report detection |
Recommended rollout
- Start with templates (low risk, high value)
- Enable custom states if teams need structured stage tracking
- Add SLA tracking when you have defined response targets
- Turn on escalations gradually to avoid alert fatigue
- Enable routing only after external integrations are tested
Setting flags
Via environment variables:
OCCURRENCES_ENABLE_TEMPLATES=true
OCCURRENCES_ENABLE_ESCALATIONS=false
Or in Django settings:
OCCURRENCES_WORKFLOW_FEATURES = {
'enable_templates': True,
'enable_custom_states': True,
'enable_sla_tracking': True,
'enable_escalations': env.bool('OCCURRENCES_ENABLE_ESCALATIONS', False),
'enable_routing': env.bool('OCCURRENCES_ENABLE_ROUTING', False),
'enable_duplicate_detection': True,
}
3) Equipment module flags
The Equipment module has fewer feature flags, focusing on core functionality.
Available flags
| Flag | Default | Description |
|---|---|---|
EQUIPMENT_ENABLE_RESERVATIONS |
True | Reservation/booking system |
EQUIPMENT_ENABLE_INSPECTIONS |
True | Inspection records |
EQUIPMENT_ENABLE_MAINTENANCE_REMINDERS |
True | Automated maintenance alerts |
EQUIPMENT_ENABLE_WARRANTY_ALERTS |
True | Warranty expiration notifications |
Background task flags
Equipment background tasks (Celery) can be individually enabled:
EQUIPMENT_CELERY_TASKS = {
'check_maintenance_due': True,
'check_warranty_expiring': True,
'check_inspection_due': True,
}
4) Occupancy module flags
The Occupancy module has configuration for data ingestion and alerting.
Available flags
| Flag | Default | Description |
|---|---|---|
OCCUPANCY_ENABLE_ALERTS |
True | Capacity and sensor alerts |
OCCUPANCY_ENABLE_PUBLIC_DASHBOARD |
True | Public-facing occupancy display |
OCCUPANCY_ENABLE_WEBSOCKET |
True | Real-time updates via WebSocket |
OCCUPANCY_ENABLE_EQUIPMENT_SYNC |
False | Sync sensors with Equipment module |
Data ingestion settings
| Setting | Default | Description |
|---|---|---|
OCCUPANCY_INGESTION_ENABLED |
True | Enable data ingestion from lakehouse |
OCCUPANCY_DATA_RETENTION_DAYS |
30 | How long to keep raw sensor readings |
OCCUPANCY_CACHE_TTL_SECONDS |
300 | Occupancy calculation cache duration |
Alert thresholds
Configurable via settings:
OCCUPANCY_ALERT_THRESHOLDS = {
'capacity_warning_percent': 80,
'capacity_critical_percent': 95,
'sensor_offline_minutes': 30,
}
5) Dynamic Forms flags
Dynamic forms have their own configuration.
Available flags
| Flag | Default | Description |
|---|---|---|
DYNAMIC_FORMS_ENABLE_HYDRATION |
True | Map form data to model records |
DYNAMIC_FORMS_ENABLE_FILE_UPLOADS |
True | File upload fields in forms |
DYNAMIC_FORMS_ENABLE_DRAFT_PREVIEW |
True | Preview draft forms before publishing |
6) Cross-module permissions
The module registry also handles permission checking:
MODULE_PERMISSIONS = {
'occurrences': {
'view': ['public', 'staff', 'manager', 'admin'],
'create': ['public', 'staff', 'admin'],
'update': ['staff', 'manager', 'admin'],
'delete': ['admin'],
},
'equipment': {
'view': ['staff', 'manager', 'admin'],
'create': ['staff', 'admin'],
'update': ['staff', 'manager', 'admin'],
'delete': ['admin'],
},
'occupancy': {
'view': ['public', 'staff', 'manager', 'admin'],
'create': ['staff', 'admin'],
'update': ['staff', 'admin'],
'delete': ['admin'],
},
}
7) Checking configuration
Via admin
Platform administrators can view enabled modules and features in Django Admin.
Via API
GET /api/config/modules/
Returns:
{
"enabled_modules": ["occurrences", "equipment", "occupancy"],
"features": {
"occurrences": {"templates": true, "sla_tracking": true, ...},
"equipment": {"reservations": true, "inspections": true, ...},
"occupancy": {"alerts": true, "public_dashboard": true, ...}
}
}
Via code
from apps.utils.module_registry import is_module_enabled
if is_module_enabled('equipment'):
# Equipment-specific logic
pass
Behind the scenes (grounded in code)
- Module registry:
apps/utils/module_registry.py - Settings:
config/settings/base.py - API router:
config/api_router.py(conditional registration) - Admin: Unfold admin configuration checks module enablement