🏗️ ResuMate Architecture
Architecture Overview
Modern, scalable Django REST API with AI integration, containerized deployment, and enterprise-grade database design for production-ready applications.
High-Level Architecture
System Components
ResuMate follows a 3-tier architecture with clear separation of concerns, microservices-ready design, and horizontal scalability for enterprise-grade performance.
graph TB
subgraph Client["Client Layer"]
WEB["Web Client<br/>React/Angular/Vue"]
MOB["Mobile App<br/>Flutter/React Native"]
API_CLIENT["External API<br/>Third-party integrations"]
end
subgraph Gateway["API Gateway Layer"]
NGINX["Nginx<br/>Load Balancer & Reverse Proxy"]
RATE["Rate Limiting<br/>DRF Throttling"]
end
subgraph App["Application Layer"]
AUTH["Authentication<br/>JWT Tokens"]
RESUME["Resume Service<br/>CRUD Operations"]
AI_SVC["AI Service<br/>Content Generation"]
JOB["Job Tracker<br/>Application Management"]
end
subgraph External["External AI Services"]
GEMINI["Google Gemini<br/>Premium AI Model"]
OPENROUTER["OpenRouter<br/>Multiple AI Models"]
end
subgraph Data["Data Layer"]
POSTGRES[("PostgreSQL<br/>Primary Database")]
REDIS[("Redis<br/>Caching & Sessions")]
FILES["File Storage<br/>Static/Media Files"]
end
WEB --> NGINX
MOB --> NGINX
API_CLIENT --> NGINX
NGINX --> RATE
RATE --> AUTH
RATE --> RESUME
RATE --> AI_SVC
RATE --> JOB
AI_SVC --> GEMINI
AI_SVC --> OPENROUTER
AUTH --> POSTGRES
RESUME --> POSTGRES
JOB --> POSTGRES
AUTH --> REDIS
RESUME --> FILES
style POSTGRES fill:#336791,color:#fff
style GEMINI fill:#4285f4,color:#fff
style OPENROUTER fill:#ff6b6b,color:#fff
style NGINX fill:#009639,color:#fff
Database Schema (ERD)
Entity Relationship Diagram
PostgreSQL database with Django's built-in auth system, optimized relationships, soft deletes, and comprehensive audit trails for enterprise-grade data management.
erDiagram
auth_user {
int id PK
string username UK
string email
string password
string first_name
string last_name
timestamp last_login
boolean is_superuser
boolean is_staff
boolean is_active
timestamp date_joined
}
resume_resume {
bigint id PK
int user_id FK
string title
text content
timestamp created_at
timestamp updated_at
}
job_tracker_jobapplication {
bigint id PK
int user_id FK
bigint resume_used_id FK
string job_title
string company_name
text original_job_description
date date_applied
string status
text notes
boolean is_deleted
boolean is_example
timestamp created_at
timestamp updated_at
}
ai_aimodel {
bigint id PK
string display_name UK
string model_name
string api_provider
string api_key_name
boolean is_active
boolean login_required
int daily_limit
string response_time_info
text description
timestamp created_at
timestamp updated_at
}
auth_group {
int id PK
string name UK
}
auth_permission {
int id PK
string name
int content_type_id FK
string codename
}
django_content_type {
int id PK
string app_label
string model
}
auth_user ||--o{ resume_resume : "owns"
auth_user ||--o{ job_tracker_jobapplication : "creates"
resume_resume ||--o{ job_tracker_jobapplication : "used_in"
auth_user ||--o{ auth_user_groups : "belongs_to"
auth_group ||--o{ auth_user_groups : "contains"
auth_user ||--o{ auth_user_user_permissions : "has"
auth_permission ||--o{ auth_user_user_permissions : "granted_to"
django_content_type ||--o{ auth_permission : "defines"
Key Database Features:
- auth_user ↔ resume_resume: One-to-Many (User can have multiple resumes)
- auth_user ↔ job_tracker_jobapplication: One-to-Many (User can have multiple job applications)
- resume_resume ↔ job_tracker_jobapplication: One-to-Many (Resume can be used for multiple applications)
- ai_aimodel: Standalone table for AI model configurations
- Django Auth System: Complete user authentication with groups and permissions
- Soft Deletes: job_tracker_jobapplication uses
is_deletedflag instead of hard deletion - Audit Trails: All main models include
created_atandupdated_attimestamps - Foreign Key Constraints: Proper CASCADE behavior with DEFERRABLE INITIALLY DEFERRED
- Unique Constraints: Username and AI model display names enforced at DB level
- :material-example:{ style="color: #9c27b0" } Example Data: job_tracker_jobapplication includes
is_exampleflag for sample data
- Auto-Generated IDs: All tables use PostgreSQL IDENTITY columns for optimal performance
- :material-index:{ style="color: #2196f3" } Indexed Foreign Keys: All FK relationships automatically indexed for fast joins
- Selective Queries: Default filtering excludes soft-deleted records
- Connection Pooling: PostgreSQL with psycopg2-binary for optimized connections
- Query Optimization: Django ORM with select_related and prefetch_related
Database Table Structure
PostgreSQL Schema Details
Complete database structure with Django's authentication system, custom applications, and optimized indexes for production performance.
Core Application Tables
Primary user authentication table with Django's built-in user model:
| Field | Type | Constraints | Description |
|---|---|---|---|
id |
integer |
PK, IDENTITY |
Auto-generated primary key |
username |
varchar(150) |
UNIQUE, NOT NULL |
Unique username for login |
email |
varchar(254) |
NOT NULL |
User email address |
password |
varchar(128) |
NOT NULL |
Hashed password |
first_name |
varchar(150) |
NOT NULL |
User's first name |
last_name |
varchar(150) |
NOT NULL |
User's last name |
is_superuser |
boolean |
NOT NULL |
Admin privileges flag |
is_staff |
boolean |
NOT NULL |
Staff access flag |
is_active |
boolean |
NOT NULL |
Account active status |
date_joined |
timestamp with time zone |
NOT NULL |
Account creation date |
last_login |
timestamp with time zone |
NULL |
Last login timestamp |
User-generated resume content with AI integration:
| Field | Type | Constraints | Description |
|---|---|---|---|
id |
bigint |
PK, IDENTITY |
Auto-generated primary key |
user_id |
integer |
FK → auth_user.id |
Resume owner reference |
title |
varchar(255) |
NOT NULL |
Resume title/name |
content |
text |
NOT NULL |
Full resume content (JSON/Markdown) |
created_at |
timestamp with time zone |
NOT NULL |
Creation timestamp |
updated_at |
timestamp with time zone |
NOT NULL |
Last modification timestamp |
Job application tracking with soft delete capability:
| Field | Type | Constraints | Description |
|---|---|---|---|
id |
bigint |
PK, IDENTITY |
Auto-generated primary key |
user_id |
integer |
FK → auth_user.id |
Application owner reference |
resume_used_id |
bigint |
FK → resume_resume.id, NULL |
Resume used for application |
job_title |
varchar(255) |
NULL |
Position title |
company_name |
varchar(255) |
NULL |
Company name |
original_job_description |
text |
NULL |
Original job posting |
date_applied |
date |
NULL |
Application submission date |
status |
varchar(20) |
NOT NULL |
Application status |
notes |
text |
NULL |
User notes |
is_deleted |
boolean |
NOT NULL |
Soft delete flag |
is_example |
boolean |
NOT NULL |
Example data flag |
created_at |
timestamp with time zone |
NOT NULL |
Creation timestamp |
updated_at |
timestamp with time zone |
NOT NULL |
Last modification timestamp |
AI service configuration and management:
| Field | Type | Constraints | Description |
|---|---|---|---|
id |
bigint |
PK, IDENTITY |
Auto-generated primary key |
display_name |
varchar(100) |
UNIQUE, NOT NULL |
User-facing model name |
model_name |
varchar(100) |
NOT NULL |
Actual AI model identifier |
api_provider |
varchar(50) |
NOT NULL |
Provider (google, openrouter) |
api_key_name |
varchar(100) |
NOT NULL |
Environment variable name |
is_active |
boolean |
NOT NULL |
Model availability status |
login_required |
boolean |
NOT NULL |
Authentication requirement |
daily_limit |
integer |
NOT NULL |
Daily usage limit |
response_time_info |
varchar(100) |
NOT NULL |
Performance information |
description |
text |
NOT NULL |
Model description |
created_at |
timestamp with time zone |
NOT NULL |
Creation timestamp |
updated_at |
timestamp with time zone |
NOT NULL |
Last modification timestamp |
Django System Tables
Complete Django authentication and authorization:
auth_group: User groups for role-based accessauth_permission: Granular permission definitionsauth_group_permissions: Many-to-many group permissionsauth_user_groups: User group membershipsauth_user_user_permissions: Direct user permissionsdjango_content_type: Content type framework for permissions
Django framework tables:
django_migrations: Database migration trackingdjango_session: Session storage (if using DB sessions)django_admin_log: Admin interface action logging
Database Indexes & Performance
Automatic Indexing
Foreign Key Indexes (Auto-created):
-- Resume table indexes
CREATE INDEX resume_resume_user_id_0b155703
ON resume_resume(user_id);
-- Job application table indexes
CREATE INDEX job_tracker_jobapplication_user_id_a3f6cbf6
ON job_tracker_jobapplication(user_id);
CREATE INDEX job_tracker_jobapplication_resume_used_id_68776f96
ON job_tracker_jobapplication(resume_used_id);
-- Authentication system indexes
CREATE INDEX auth_user_groups_user_id_6a12ed8b
ON auth_user_groups(user_id);
CREATE INDEX auth_user_user_permissions_user_id_a95ead1b
ON auth_user_user_permissions(user_id);
Data Integrity
Foreign Key Constraints with Deferred Checking:
API Request Flow
Request Processing Pipeline
Complete request lifecycle from client to response with security, validation, and AI integration for seamless user experience.
sequenceDiagram
participant Client
participant Nginx
participant Django
participant JWT
participant AI
participant DB
participant External
Note over Client,External: AI Resume Generation Flow
Client->>Nginx: POST /api/ai/generate/
Nginx->>Django: Forward Request
Django->>JWT: Validate Token (Optional)
alt Authenticated User
JWT-->>Django: Valid User
else Anonymous User
JWT-->>Django: Anonymous Access
end
Django->>Django: Validate Request Data
Django->>DB: Check AI Model Permissions
DB-->>Django: Model Configuration
Django->>AI: Process Generation Request
AI->>External: Call AI API (Gemini/OpenRouter)
External-->>AI: AI Response
AI-->>Django: Processed Content
Django->>DB: Save Resume (resume_resume table)
DB-->>Django: Resume ID
Django-->>Client: Response with resume_id and content
Note over Client,External: Error Handling
alt API Error
External-->>AI: AI Service Error
AI-->>Django: Exception
Django-->>Client: 503 Service Unavailable
else Rate Limit Exceeded
Django-->>Client: 429 Too Many Requests
else Authentication Required
JWT-->>Django: Invalid/Missing Token
Django-->>Client: 401 Unauthorized
end
Flow Breakdown:
Technology Stack
Modern Tech Stack
Enterprise-grade technologies chosen for scalability, performance, and maintainability in production environments.
| Component | Technology | Version | Purpose |
|---|---|---|---|
| Framework | Django | 5.0.14 | Web framework & ORM |
| API Layer | Django REST Framework | Latest | RESTful API development |
| Database | PostgreSQL | 16+ | Primary data storage |
| Caching | Redis | 7+ | High-performance caching & API optimization |
| Authentication | JWT | simplejwt | Stateless authentication |
| Service | Provider | Model | Access Level |
|---|---|---|---|
| Google Gemini | Google AI | gemini-2.0-flash-exp | Authenticated (5/day) |
| Deepseek | OpenRouter | deepseek/deepseek-r1 | Public (Unlimited) |
| Cypher | OpenRouter | teknium/openhermes-2.5 | Public (Unlimited) |
| Component | Technology | Purpose |
|---|---|---|
| Containerization | Docker + Compose | Development & deployment |
| CI/CD | GitHub Actions | Automated testing & deployment |
| Web Server | Gunicorn + Nginx | Production WSGI server |
| Monitoring | Django Logging | Error tracking & performance |
| Static Files | WhiteNoise | Static asset serving |
Redis Caching Architecture
High-Performance Caching System
Redis implementation for API response optimization, reducing database load and delivering sub-20ms response times for cached endpoints.
Cache Configuration & Strategy
Redis Setup:
# Docker Compose Configuration
redis:
image: redis:alpine
container_name: resumate_redis_prod
restart: always
command: redis-server --maxmemory 256mb --maxmemory-policy allkeys-lru
volumes:
- redis_data_prod:/data
Cache Strategy:
| Parameter | Value | Description |
|---|---|---|
| Memory Limit | 256MB |
Maximum Redis memory usage |
| Eviction Policy | allkeys-lru |
Least Recently Used eviction |
| Persistence | Volume-backed |
Data persistence across container restarts |
| Connection | Local network |
Container-to-container communication |
Cached Endpoints Implementation
Endpoint: /api/ai/models/
# Cache Implementation
CACHE_KEY = "ai_models_list"
CACHE_TIMEOUT = 60 * 60 # 1 hour
def get(self, request):
# Try cache first
cached_data = cache.get(self.CACHE_KEY)
if cached_data:
return Response({
'cache_status': 'HIT (Response from Redis cache)',
'data': cached_data
}, headers={'X-Cache-Status': 'HIT'})
# Cache miss - fetch from database
active_models = ai_aimodel.objects.filter(is_active=True)
serializer = AIModelSerializer(active_models, many=True)
cache.set(self.CACHE_KEY, serializer.data, self.CACHE_TIMEOUT)
return Response({
'cache_status': 'MISS (Response from database)',
'data': serializer.data
}, headers={'X-Cache-Status': 'MISS'})
Endpoint: /api/example-job-applications/
# Cache implementation for example job applications
CACHE_KEY = "example_job_applications_list"
CACHE_TIMEOUT = 60 * 60 # 1 hour
def get(self, request):
cached_data = cache.get(self.CACHE_KEY)
if cached_data:
return Response({
'cache_status': 'HIT (Response from Redis cache)',
'data': cached_data
}, headers={'X-Cache-Status': 'HIT'})
# Cache miss - fetch example applications
example_apps = job_tracker_jobapplication.objects.filter(
is_example=True,
is_deleted=False
)
serializer = JobApplicationSerializer(example_apps, many=True)
cache.set(self.CACHE_KEY, serializer.data, self.CACHE_TIMEOUT)
return Response({
'cache_status': 'MISS (Response from database)',
'data': serializer.data
}, headers={'X-Cache-Status': 'MISS'})
Performance Metrics
Cache Hit Ratio: 85-90% in production
Response Time Improvements:
- Cache HIT:
~10-20ms⚡ - Cache MISS:
~80-150ms🔄 - Performance Gain:
85% fasterfor cached requests
Database Load Reduction:
- Fewer DB Queries:
90% reductionfor cached endpoints - Improved Scalability: Better concurrent request handling
- Resource Efficiency: Lower CPU and memory usage
Security Architecture
Security Features
Multi-layered security approach with authentication, authorization, and data protection for enterprise-grade security.
graph LR
subgraph Security["Security Layers"]
subgraph Network["Network Security"]
HTTPS["HTTPS/TLS"]
CORS["CORS Policy"]
NGINX_SEC["Nginx Security Headers"]
end
subgraph Application["Application Security"]
JWT["JWT Tokens"]
RATE_LIMIT["Rate Limiting"]
VALIDATION["Input Validation"]
end
subgraph DataSec["Data Security"]
DB_ENCRYPT["DB Encryption"]
SOFT_DELETE["Soft Deletes"]
API_KEYS["API Key Management"]
end
end
HTTPS --> JWT
CORS --> RATE_LIMIT
NGINX_SEC --> VALIDATION
JWT --> DB_ENCRYPT
RATE_LIMIT --> SOFT_DELETE
VALIDATION --> API_KEYS
style HTTPS fill:#d73027,color:#fff
style JWT fill:#1a9850,color:#fff
style DB_ENCRYPT fill:#313695,color:#fff
Security Implementation:
- JWT Tokens: Stateless, secure token-based authentication
- Token Refresh: Automatic token renewal for seamless UX
- Anonymous Access: Limited functionality for non-authenticated users
- Permission Levels: Granular access control per endpoint
- Environment Variables: Sensitive data stored securely
- API Key Rotation: Support for key rotation without downtime
- Soft Deletes: Data retention for audit and recovery
- SQL Injection Protection: Django ORM prevents SQL injection
- Rate Limiting: Per-user and per-endpoint throttling
- Request Size Limits: Protection against large payload attacks
- Connection Pooling: Efficient database connection management
- Static File Security: Secure serving of user-generated content
Scalability Design
Horizontal Scaling
Designed for growth with microservices-ready architecture and cloud deployment for enterprise-scale applications.
graph TB
subgraph LoadBalancer["Load Balancer"]
LB["Load Balancer<br/>Nginx/HAProxy"]
end
subgraph AppServers["Application Servers"]
APP1["Django Instance 1"]
APP2["Django Instance 2"]
APP3["Django Instance 3"]
end
subgraph DataLayer["Data Layer"]
DB_MASTER[("PostgreSQL Master")]
DB_READ1[("Read Replica 1")]
DB_READ2[("Read Replica 2")]
REDIS_CLUSTER[("Redis Cluster")]
end
subgraph AIServices["AI Services"]
AI_POOL["AI Service Pool<br/>Multiple API Keys"]
end
LB --> APP1
LB --> APP2
LB --> APP3
APP1 --> DB_MASTER
APP2 --> DB_READ1
APP3 --> DB_READ2
APP1 --> REDIS_CLUSTER
APP2 --> REDIS_CLUSTER
APP3 --> REDIS_CLUSTER
APP1 --> AI_POOL
APP2 --> AI_POOL
APP3 --> AI_POOL
style LB fill:#2ecc71,color:#fff
style DB_MASTER fill:#e74c3c,color:#fff
style DB_READ1 fill:#3498db,color:#fff
style DB_READ2 fill:#3498db,color:#fff
style REDIS_CLUSTER fill:#e67e22,color:#fff
Scalability Features:
- Stateless Design: No server-side sessions, JWT for authentication
- Docker Containers: Easy horizontal scaling with container orchestration
- Load Balancing: Multiple Django instances behind load balancer
- Microservices Ready: Clear service boundaries for future splitting
- Read Replicas: Separate read and write database instances
- Connection Pooling: Efficient database connection management with Django CONN_MAX_AGE
- Query Optimization: Indexed foreign keys and relationship optimization
- Caching Strategy: Redis for API response caching with 85-90% hit ratio
- Auto-Generated IDs: PostgreSQL IDENTITY columns for optimal ID generation
- Multiple API Keys: Round-robin across different API keys
- Model Selection: Dynamic AI model selection based on load
- Retry Logic: Automatic retry with exponential backoff
- Circuit Breaker: Fail-fast pattern for external service calls
Deployment Architecture
Production Deployment
Docker-based deployment with CI/CD automation and environment management for seamless production operations.
graph TB
subgraph Development["Development"]
DEV_CODE["Local Development<br/>Docker Compose"]
GIT["Git Repository<br/>GitHub"]
end
subgraph CICD["CI/CD Pipeline"]
ACTIONS["GitHub Actions"]
TESTS["Automated Tests"]
BUILD["Docker Build"]
REGISTRY["Docker Hub<br/>Image Registry"]
end
subgraph Production["Production Environment"]
PROD_SERVER["Production Server<br/>Linux/Cloud"]
PROD_DB[("PostgreSQL<br/>Production")]
PROD_REDIS[("Redis<br/>Production")]
NGINX_PROD["Nginx<br/>Reverse Proxy"]
end
DEV_CODE --> GIT
GIT --> ACTIONS
ACTIONS --> TESTS
TESTS --> BUILD
BUILD --> REGISTRY
REGISTRY --> PROD_SERVER
PROD_SERVER --> PROD_DB
PROD_SERVER --> PROD_REDIS
NGINX_PROD --> PROD_SERVER
style ACTIONS fill:#2ecc71,color:#fff
style REGISTRY fill:#0db7ed,color:#fff
style PROD_SERVER fill:#e74c3c,color:#fff
style NGINX_PROD fill:#009639,color:#fff
Deployment Process:
# GitHub Actions Workflow
name: CI/CD Pipeline
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Run Tests
run: docker-compose -f docker-compose.test.yml up --abort-on-container-exit
build:
needs: test
runs-on: ubuntu-latest
steps:
- name: Build & Push Docker Image
run: |
docker build -t resumate:${{ github.sha }} .
docker push resumate:${{ github.sha }}
- Multi-Stage Builds: Optimized production images
- Environment Separation: Different configurations for dev/staging/prod
- Health Checks: Container health monitoring and auto-restart
- Volume Management: Persistent data and log volumes
- Application Logs: Structured logging with Django logging framework
- Error Tracking: Centralized error collection and alerting
- Performance Metrics: Database query optimization and response times
- Backup Strategy: Automated database backups and recovery procedures
Design Decisions & Trade-offs
Architectural Choices
Key decisions made for performance, maintainability, and scalability in production environments.
Why Django REST Framework?
✅ Advantages: - Rapid API development with built-in serialization - Robust authentication and permission system - Extensive ecosystem and community support - Built-in admin interface for data management - ORM provides database abstraction and migrations
⚠️ Trade-offs: - Higher memory footprint compared to FastAPI - Python GIL limitations for CPU-intensive tasks - Learning curve for Django conventions
Why PostgreSQL over MongoDB?
✅ Advantages: - ACID compliance for data integrity - Complex relationships between Users, Resumes, JobApplications - Mature ecosystem with excellent Django integration - Advanced indexing and query optimization - JSON field support for flexible resume content storage
⚠️ Trade-offs: - Vertical scaling limitations - Schema migrations required for structure changes - :material-complexity:{ style="color: #9c27b0" } More complex than NoSQL for simple document storage
Why Multiple AI Providers?
✅ Advantages: - Risk mitigation - no single point of failure - Cost optimization - use free models for anonymous users - Performance diversity - different models for different use cases - Rate limit distribution across multiple services
⚠️ Trade-offs: - Increased complexity in AI service management - Multiple API keys and configurations to maintain - Inconsistent response formats between providers
Why JWT over Session-based Authentication?
✅ Advantages: - Stateless - no server-side session storage required - Scalable across multiple server instances - Mobile-friendly with token-based approach - Built-in expiration and refresh token support
⚠️ Trade-offs: - Token size larger than session IDs - Cannot revoke tokens before expiration - More complex client-side token management
Architecture Summary
ResuMate's architecture successfully balances performance, scalability, and maintainability through:
- Clear Separation of Concerns: Distinct layers for presentation, business logic, and data
- Modular Design: Independent apps that can evolve separately
- Performance Optimization: Caching, database indexing, and efficient query patterns
- Security First: Multi-layered security with authentication, authorization, and data protection
- Scalability Ready: Horizontal scaling support with containerization and load balancing
- DevOps Integration: Automated CI/CD with testing, building, and deployment pipelines