Architecture Diagram
InterviewGuide is built as a modular monolithic application with clear separation of concerns between frontend, backend, and infrastructure layers.High-Level Architecture
The system follows a layered architecture pattern:Frontend Layer
React 18.3 + TypeScript 5.6 SPA with Vite 5.4 build system
Backend Layer
Spring Boot 4.0 + Java 21 with modular service architecture
Data Layer
PostgreSQL + pgvector for relational and vector data storage
Project Structure
The backend follows a modular architecture organized by business domain:Core Components
1. Module Architecture
Each business module (resume, interview, knowledgebase) follows a consistent structure:Module Organization Pattern
Module Organization Pattern
Controller Layer: REST API endpoints
- Request validation
- Response formatting
- HTTP-level concerns
- Domain operations
- Transaction management
- Orchestration between components
- JPA repositories for database access
- Query methods and specifications
- Stream producers for task queuing
- Stream consumers for background processing
- JPA entities for database mapping
- DTOs for API communication
- Request/Response objects
2. Common Infrastructure
Shared components provide cross-cutting functionality:- Async Processing
- AI Integration
- Cross-Cutting Concerns
Template-based pattern using abstract base classes:
AbstractStreamProducer<T>: Base for message producersAbstractStreamConsumer<T>: Base for message consumers- Handles retries, state transitions, error handling
app/src/main/java/interview/guide/common/async/Data Flow Patterns
Synchronous Request Flow
For immediate operations like querying data or initiating tasks:Asynchronous Processing Flow
For long-running AI operations (resume analysis, vectorization, interview evaluation):Component Interaction
Resume Analysis Module
Complete lifecycle from upload to completed analysis:File Upload
User uploads resume file (PDF/DOCX/DOC/TXT)
- File stored in S3-compatible storage (RustFS/MinIO)
- Resume entity created with
PENDINGstatus - Content hash calculated for duplicate detection
Task Queuing
AnalyzeStreamProducer sends message to Redis Stream- Message includes:
resumeId,content,retryCount - Stream key:
resume:analyze:stream - Immediate response to client with task ID
Background Processing
AnalyzeStreamConsumer processes the task- Updates status to
PROCESSING - Calls Spring AI with structured output parsing
- Extracts: skills, experience, education, score
- Saves analysis results to database
Interview Module
Real-time mock interview with intelligent follow-ups:Session-Based Architecture: Each interview session maintains state in Redis cache for fast access, with persistent storage in PostgreSQL for history and reporting.
- Session Creation: POST
/api/interview/sessionscreates a new session based on resume content - Question Generation: AI generates initial question from resume analysis
- Answer Submission: POST
/api/interview/sessions/{id}/answerswith streaming SSE response - Follow-up Questions: Configurable multi-turn conversation (default: 1 follow-up per main question)
- Batch Evaluation: Answers evaluated in batches (default: 8 per batch) to avoid token limits
- Report Generation: Async aggregation of evaluation results into PDF report
Knowledge Base Module
RAG-powered question answering system:Document Ingestion
- Apache Tika parses PDF/DOCX/Markdown
- Content chunked with overlap for context
- Async vectorization via Redis Stream
- Embeddings stored in pgvector
Query Processing
- Question converted to embedding vector
- Similarity search in pgvector
- Top-k relevant chunks retrieved
- LLM generates answer with context
- Streaming response via SSE
State Management
Async Task State Machine
All async operations follow this state flow:PENDING: Task queued, waiting for consumerPROCESSING: Consumer actively processingCOMPLETED: Successfully finishedFAILED: Failed after max retries (3 attempts)
Technology Choices
Why Redis Stream over Kafka?
Why Redis Stream over Kafka?
Architecture Simplification: Redis Stream provides sufficient messaging capabilities without the operational overhead of Kafka:
- Consumer groups for load distribution
- Message acknowledgment and replay
- Built-in persistence and recovery
- Lower resource requirements
- Single dependency for both caching and messaging
Why pgvector over Dedicated Vector DB?
Why pgvector over Dedicated Vector DB?
Unified Data Store: Using PostgreSQL with pgvector extension eliminates need for separate vector database:
- Single source of truth for relational and vector data
- ACID transactions across all data types
- Simplified deployment and backup
- SQL joins between vectors and metadata
- Sufficient performance for application scale (under 10k documents)
Next Steps
Tech Stack
Detailed breakdown of all technologies and version dependencies
Async Processing
Deep dive into Redis Streams implementation with code examples
