Skip to main content

Overview

The Mock Interview feature provides a realistic interview simulation experience by generating personalized questions based on resume content, supporting multi-round intelligent follow-up questions, and delivering detailed performance evaluations. All session state is managed via Redis cache with database persistence for recovery.
Interview sessions are cached in Redis for fast access, with automatic fallback to database when cache expires.

Creating an Interview Session

Users can start a mock interview based on an analyzed resume:
POST /api/interview/sessions
{
  "resumeText": "Full resume content...",
  "resumeId": 123,
  "questionCount": 5,
  "forceCreate": false
}
Parameters:
  • resumeText: Required, extracted text from resume
  • resumeId: Optional, links session to a specific resume
  • questionCount: Number of questions (default: 5)
  • forceCreate: If false, returns existing unfinished session

Session Creation Flow

1

Check for Existing Session

If forceCreate is false and resumeId is provided, the system checks for unfinished sessions:
// InterviewSessionService.java:45-51
if (request.resumeId() != null && !Boolean.TRUE.equals(request.forceCreate())) {
    Optional<InterviewSessionDTO> unfinishedOpt = findUnfinishedSession(request.resumeId());
    if (unfinishedOpt.isPresent()) {
        return unfinishedOpt.get();
    }
}
2

Generate Session ID

A unique 16-character session identifier is created:
// InterviewSessionService.java:54
String sessionId = UUID.randomUUID().toString().replace("-", "").substring(0, 16);
3

Generate Questions

The AI generates personalized questions based on resume content, avoiding previously asked questions:
// InterviewSessionService.java:60-70
List<String> historicalQuestions = persistenceService.getHistoricalQuestionsByResumeId(resumeId);
List<InterviewQuestionDTO> questions = questionService.generateQuestions(
    request.resumeText(),
    request.questionCount(),
    historicalQuestions
);
4

Cache in Redis

Session data is stored in Redis with TTL:
// InterviewSessionService.java:73-80
sessionCache.saveSession(
    sessionId, resumeText, resumeId,
    questions, 0, SessionStatus.CREATED
);
5

Persist to Database

Session metadata is saved for recovery:
// InterviewSessionService.java:84-89
persistenceService.saveSession(
    sessionId, request.resumeId(),
    questions.size(), questions
);

Session Status Lifecycle

Interview sessions progress through four distinct states:
// InterviewSessionEntity.java:88-93
public enum SessionStatus {
    CREATED,      // Session initialized, no answers yet
    IN_PROGRESS,  // User is answering questions
    COMPLETED,    // All questions answered or early submission
    EVALUATED     // AI evaluation report generated
}

Intelligent Question Generation

The system generates questions with optional follow-up questions:

Main Questions

Core interview questions based on:
  • Resume skills and experience
  • Project descriptions
  • Technical keywords
  • Job level indicators

Follow-up Questions

Intelligent follow-ups that:
  • Dive deeper into main topics
  • Challenge assumptions
  • Test practical knowledge
  • Configurable count (default: 1)

Configuration

# application.yml
app:
  interview:
    follow-up-count: 1  # Number of follow-ups per main question
Follow-up questions are generated in sequence after the main question is answered, creating a natural interview flow.

Answering Questions

Get Current Question

GET /api/interview/sessions/{sessionId}/question
Response:
{
  "completed": false,
  "question": {
    "index": 0,
    "question": "Explain the benefits of using Redis in your architecture",
    "category": "TECHNICAL",
    "answer": null
  }
}

Save Answer (Draft)

Save an answer without progressing to the next question:
PUT /api/interview/sessions/{sessionId}/answers
{
  "questionIndex": 0,
  "answer": "Redis provides..."
}
This allows users to save progress without committing. The currentIndex remains unchanged.

Submit Answer

Submit an answer and move to the next question:
POST /api/interview/sessions/{sessionId}/answers
{
  "questionIndex": 0,
  "answer": "Redis provides in-memory caching, pub/sub messaging, and supports various data structures..."
}
1

Validate Question Index

Ensure the index is valid and matches current position
2

Update Answer

Store the answer in the question object:
// InterviewSessionService.java:287-289
InterviewQuestionDTO answeredQuestion = question.withAnswer(request.answer());
questions.set(index, answeredQuestion);
3

Move to Next Question

Increment currentIndex by 1
4

Check Completion

If this was the last question:
  • Update status to COMPLETED
  • Set evaluation status to PENDING
  • Send evaluation task to Redis Stream
5

Update Cache and Database

Persist answer and update session state in both Redis and database

Early Submission

Users can submit the interview before answering all questions:
POST /api/interview/sessions/{sessionId}/complete
This:
  1. Updates status to COMPLETED
  2. Triggers asynchronous evaluation for answered questions
  3. Unanswered questions are scored as 0
Early submission cannot be undone. Ensure users confirm this action.

Evaluation Process

Evaluation happens asynchronously after the interview is completed:
1

Evaluation Task Queued

When the last answer is submitted or interview is completed early:
// InterviewSessionService.java:322-324
persistenceService.updateEvaluateStatus(sessionId, AsyncTaskStatus.PENDING, null);
evaluateStreamProducer.sendEvaluateTask(sessionId);
2

Batch Evaluation Strategy

To avoid token limits, answers are evaluated in batches:
# application.yml
app:
  interview:
    evaluation:
      batch-size: 8  # Evaluate 8 answers per AI call
Large interviews (10+ questions) can exceed AI model token limits. The system:
  • Divides answers into configurable batches (default: 8)
  • Evaluates each batch independently
  • Aggregates scores and feedback
  • Generates a final summary report
This ensures stable evaluation even for lengthy interviews.
3

Individual Answer Scoring

Each answer is scored on:
  • Accuracy (0-40 points): Technical correctness
  • Completeness (0-30 points): Coverage of key points
  • Clarity (0-30 points): Communication effectiveness
Total per answer: 0-100 points
4

Overall Report Generation

The system generates:
  • Overall score: Weighted average of all answers
  • Strengths: List of strong points across answers
  • Improvements: Actionable suggestions for weak areas
  • Reference answers: Model answers for each question
5

Status Update

Evaluation status transitions:
PENDING → PROCESSING → COMPLETED
Session status updates to EVALUATED when report is ready.

Evaluation Status Flow

Viewing Interview Reports

Retrieve the comprehensive evaluation report:
GET /api/interview/sessions/{sessionId}/report
{
  "sessionId": "abc123def456",
  "overallScore": 78,
  "overallFeedback": "Strong technical knowledge with room for improvement in communication...",
  "strengths": [
    "Deep understanding of microservices architecture",
    "Practical experience with Redis and PostgreSQL",
    "Clear explanation of trade-offs"
  ],
  "improvements": [
    "Provide more specific examples from projects",
    "Structure answers with introduction-body-conclusion",
    "Quantify impact with metrics when possible"
  ],
  "questionEvaluations": [
    {
      "questionIndex": 0,
      "question": "Describe your experience with Spring Boot",
      "userAnswer": "I have used Spring Boot for...",
      "score": 85,
      "feedback": "Excellent explanation with practical examples",
      "referenceAnswer": "Spring Boot simplifies..."
    }
  ]
}

PDF Export

Generate a professional PDF report:
GET /api/interview/sessions/{sessionId}/export
The exported PDF includes:
  1. Cover Page
    • Session ID and timestamp
    • Resume reference (if linked)
    • Overall score
  2. Executive Summary
    • Overall feedback
    • Key strengths
    • Priority improvements
  3. Detailed Evaluation
    • Each question with:
      • Question text and category
      • User’s answer
      • Score breakdown
      • Detailed feedback
      • Reference answer
  4. Performance Trends (if multiple sessions)
    • Score progression
    • Category strengths
Generated using iText 8 with Chinese font support.

Session Recovery

Sessions are automatically recovered from the database if Redis cache expires:
// InterviewSessionService.java:165-216
private CachedSession restoreSessionFromDatabase(String sessionId) {
    Optional<InterviewSessionEntity> entityOpt = persistenceService.findBySessionId(sessionId);
    return entityOpt.map(this::restoreSessionFromEntity).orElse(null);
}
1

Cache Miss Detection

When Redis cache doesn’t contain the session
2

Database Query

Retrieve session entity by sessionId
3

Restore Questions

Deserialize questions from JSON
4

Restore Answers

Load saved answers and merge with questions
5

Re-cache

Save restored session back to Redis
Users experience seamless continuity even if Redis is restarted or cache expires.

Deleting Sessions

Remove an interview session and all associated data:
DELETE /api/interview/sessions/{sessionId}
This deletes:
  • Session entity
  • All answer records
  • Cached data in Redis

Rate Limiting

Protection against abuse:
// InterviewController.java:37
@RateLimit(dimensions = {RateLimit.Dimension.GLOBAL, RateLimit.Dimension.IP}, count = 5)
  • Session creation: 5 per time window
  • Answer submission: 10 per time window (global)

Best Practices

Check for Unfinished Sessions

Before creating a new session, call /sessions/unfinished/{resumeId} to resume existing sessions.

Implement Auto-save

Use the PUT /answers endpoint to periodically save drafts as users type.

Poll Evaluation Status

After completion, poll every 3-5 seconds for evaluation completion:
while (session.evaluateStatus !== 'COMPLETED') {
  await sleep(3000);
  session = await getSession(sessionId);
}

Handle Long Evaluations

Evaluation can take 30-60 seconds for large interviews. Show progress indicators.

Error Handling

Error: INTERVIEW_SESSION_NOT_FOUNDCauses:
  • Invalid session ID
  • Session deleted
  • Session expired (both Redis and DB)
Solution: Start a new interview session.
Error: INTERVIEW_ALREADY_COMPLETEDCause: Attempting to submit answers to a completed sessionSolution: View the report instead of trying to submit more answers.
Error: evaluateStatus = FAILEDCauses:
  • AI API timeout
  • Token limit exceeded (despite batching)
  • Invalid answer format
Solution: Check evaluateError field for details. Users can manually trigger re-evaluation (if endpoint exists).

Architecture Diagram

For complete API reference, see:

Build docs developers (and LLMs) love