Project Blueprints
Weak academic projects are the #1 resume rejection reason. Each blueprint gives the architecture, an 8-week build plan, ATS bullets with metric slots, and the defence answers interviewers probe.
Enterprise Task Management System with RBAC, Microservices & Redis Caching
Hiring managers reject toy CRUD apps. This project demonstrates the three things service and product interviews probe: authorisation design, service decomposition, and cache-aware data access — all defensible at depth.
System architecture
[Client SPA]
│ HTTPS
[API Gateway / Nginx]
├── auth-service (JWT issue/verify, refresh rotation)
├── task-service (CRUD, filters, assignments) ── Redis (lists, hot queries)
├── notification-service (email on assignment) ← queue
└── audit-service (immutable activity log)
└── all services → PostgreSQL (per-service schemas)Data flow
Login → auth-service verifies credentials, issues short-lived JWT + refresh cookie. Client calls task-service with Bearer token; gateway verifies signature only (no DB hit). Task reads check Redis first (list cache keyed by user+filter, TTL 60s, invalidated on write). Assignment events publish to a queue consumed by notification-service. All state changes append to audit-service.
Stack & standards
Backend: Node.js/NestJS or Spring Boot · PostgreSQL · Redis · RabbitMQ/Redis Streams
Auth: JWT access (15 min) + refresh rotation · bcrypt password hashing · Role model: admin / manager / member
Infra: Docker Compose · GitHub Actions CI · Nginx gateway
Standards: OWASP Top 10 (auth, injection, session) · JWT best practices (RFC 7519) · RBAC per NIST model
Implementation milestones
Weeks 1–2 — Domain & auth core
- Schema: users, teams, tasks, assignments, audit_log
- auth-service with signup/login/refresh
- Role model + guards/middleware
Weeks 3–4 — Task service
- CRUD + filters (status, assignee, due date)
- Assignment flow + notifications via queue
- Pagination + indexes on (assignee, status)
Weeks 5–6 — Cache & hardening
- Redis list caching with write-through invalidation
- Rate limiting, input validation, audit trail
- Load test (k6) and fix the top bottleneck
Weeks 7–8 — Ship & document
- Dockerise all services
- CI pipeline: lint → test → build → push images
- README with architecture diagram + trade-offs
ATS resume bullets (copy with your real numbers)
Designed and implemented a 3-service task platform (NestJS + PostgreSQL + Redis) with role-based access control, reducing unauthorised-access surface by enforcing server-side permission checks on every route.
Cut p95 task-list latency 4× (380ms → 95ms) by caching filtered lists in Redis with write-through invalidation.
Built JWT access/refresh rotation with revocation, eliminating the session-fixation class of bugs found in the first security review.
Containerised the stack with Docker Compose and a GitHub Actions pipeline running lint, unit and integration tests on every push.
Load-tested with k6 at 200 rps, identified a missing composite index, and reduced DB CPU from 85% to 30%.
Top 5 interview defence questions
Why microservices for a student project — isn't that overkill?
It is, at this scale — and I say so. I kept three services only because auth, tasks and notifications have different scaling and failure modes (auth is CPU-light but security-critical; notifications are bursty). The honest answer plus the isolation reasoning scores better than pretending it's mandatory.
How do you prevent privilege escalation between roles?
Authorisation is enforced server-side per route via guards that resolve the role from the verified JWT — never from the request body. Managers can assign but not delete; deletion is admin-only and audit-logged.
Why cache lists and not individual tasks?
Reads are filter-shaped (my open tasks, team's overdue), so I cache at the query level. Individual task reads hit a primary-key lookup which is already fast. Invalidation on any write touches the affected user's list keys.
What happens if Redis dies?
The app degrades, not fails: reads fall through to PostgreSQL, writes continue, latency rises. Cache failure must never break correctness — that invariant drove the cache-aside choice.
How are JWTs revoked before expiry?
Access tokens aren't revoked (short 15-min life bounds the damage); refresh tokens are rotated and the old one is denylisted in Redis. Logout revokes the refresh chain.
Building it? Keep a decision log from day one — every "why did you choose X?" answer lives in it. Then practise the defence questions aloud before the AI mock interview.