Part 7: Configuring Celery, Redis & Background Task Architecture
Module: Module 1: Architecture, Monorepo Setup & Tooling
Category: Technology
Keywords: django, graphql, angular, erp, architecture, docker
Meta Description: Decoupling heavy ERP tasks (fee invoices, marksheet PDFs, email alerts) into background worker queues.
1. Executive Summary & System Architecture
Architect distributed asynchronous task processing using Celery backed by Redis message brokers.
In enterprise Educational Resource Planning (ERP) systems, orchestrating students, faculty, schedules, attendance, grading, and finances demands a robust, loosely-coupled architecture. We pair Django (leveraging its robust ORM, transactional integrity, and battle-tested security) with GraphQL (providing flexible, client-driven data graphs with zero over-fetching) and Angular (featuring strict TypeScript typing, Standalone components, reactive Signals, and Apollo Client normalization).
2. Backend Database Modeling (Django ORM & PostgreSQL)
Below is the production-grade Django model definition enforcing data integrity, foreign key constraints, indexes, and audit metadata:
# backend/apps/erp/models.py
from celery import Celery
import os
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings.production')
app = Celery('erp_tasks')
app.config_from_object('django.conf:settings', namespace='CELERY')
app.autodiscover_tasks()
Key Architectural Highlights:
- Audit Logging: Inherits from a base audit model capturing
created_at,updated_at,created_by, and soft-delete flags. - Index Optimization: Explicit database indexes (
db_index=True,indexes=[models.Index(...)]) positioned for high-frequency queries. - Validation: Enforces domain constraints via clean validation methods and unique constraints across academic years and tenant boundaries.
3. GraphQL API Layer (Types, Queries & Mutations)
The GraphQL layer exposes precise schema definitions, input validation, and transactional mutation execution:
# backend/apps/erp/schema.py
# GraphQL mutation dispatching async task
class GenerateReportCardsMutation(graphene.Mutation):
task_id = graphene.String()
class Arguments:
exam_id = graphene.ID(required=True)
def mutate(self, info, exam_id):
task = generate_batch_pdf_task.delay(exam_id)
return GenerateReportCardsMutation(task_id=task.id)
Resolver & Data Fetching Patterns:
- Batch Loading: Resolvers integrate with
DataLoaderto eliminate N+1 database queries when fetching nested relationships. - Permission Enforcement: Mutations verify caller authorization via role-based access decorators before touching the database.
- Transactional Consistency: Multi-table updates execute inside
transaction.atomic()context blocks to ensure ACID atomicity.
4. Frontend Angular Implementation (Signals & Apollo Client)
The modern Angular implementation features Standalone components, reactive Signals, and type-safe Apollo Client interactions:
// frontend/src/app/erp/components/feature.component.ts
// Angular polling or subscription for background task progress
import { Component, signal } from '@angular/core';
@Component({
selector: 'app-task-progress',
standalone: true,
template: `<div class="text-sm">Status: {{ taskStatus() }}</div>`
})
export class TaskProgressComponent {
taskStatus = signal('PROCESSING...');
}
Frontend Architectural Patterns:
- Reactivity with Signals: Uses Angular
signal(),computed(), and effect primitives for fine-grained DOM updates without unnecessary change detection cycles. - Type-Safe GraphQL: Consumes strongly-typed operations generated by
@graphql-codegen. - User Feedback: Integrates reactive loading state indicators, optimistic UI updates, and error handling toasts.
5. Security, Permissions & Multi-Tenancy
Restrict Redis broker access with strong AUTH passwords and isolate task worker execution from public API servers.
6. Critical Pitfalls & Production Anti-Patterns
When deploying this module in large-scale institutions with thousands of concurrent users, avoid these traps:
- Executing slow PDF rendering or bulk email dispatches inside synchronous HTTP requests.
- Neglecting Celery worker task timeouts, causing zombie tasks.
- Unbounded Redis memory growth caused by unexpiring task results.
7. Enterprise Best Practices & Production Checklist
- ✅ Route long-running tasks to dedicated Celery queues (e.g., pdf_queue, email_queue).
- ✅ Set celery task time limits (time_limit=300, soft_time_limit=240).
- ✅ Use Celery Beat for scheduled midnight tasks (e.g. late fee calculations).
- ✅ Monitor queue backlogs with Flower or Prometheus exporters.
Part 7 of the comprehensive Fullstack Student ERP Tutorial Series.

