Building an AI Mock Interview Platform: Architecture Deep Dive

- Published on
- Tech Stack
- Next.js, Lambda, DynamoDB, OpenAI
- Infrastructure
- SST v3 + AWS
- Auth
- Cognito + Google OAuth
- Analytics
- PostHog + GA
Earlier this year I launched Interview Sparring, an AI-powered platform for practicing job interviews. This post is a deep dive into the architecture: how the pieces fit together, what I learned building it, and the trade-offs I made along the way.
Hi there! Want to support me?
The Core Idea
Most interview preparation is passive: reading guides, memorizing answers, maybe recording yourself. Interview Sparring makes it active. You start a session, the AI asks you behavioral or technical questions, you answer out loud, and you get immediate, structured feedback on what you did well and what to improve.
The platform supports multiple interview types: behavioral, technical, consulting case studies, and role-specific formats. Users upload their resume and the AI tailors questions to their background. After each session, they get a multi-dimensional score covering communication, structure, specificity, and confidence.
The Backend: Domain-Driven Serverless
The backend is a collection of Lambda functions behind API Gateway V2, organized using Domain-Driven Design principles. Each bounded context — sessions, billing, documents, skills, stories — has its own set of handlers, services, and DynamoDB tables.
apps/backend/src/application/services/├── interview.service.ts # Orchestrates interview sessions├── interview/│ └── evaluate-answer.ts # AI-powered answer evaluation├── session.service.ts # Session lifecycle management├── session-scoring.ts # Multi-dimensional scoring├── realtime-token.service.ts # WebRTC/WebSocket tokens├── openai-client.service.ts # OpenAI API abstraction├── resumeAnalysis.service.ts # Resume analysis and feedback└── user.service.ts # User profiles and progress
The interview.service.ts is the brain. It manages the interview lifecycle: fetching the next question, sending the user's answer to OpenAI for evaluation, computing scores across dimensions, and generating actionable feedback. The openai-client.service.ts abstracts the API calls so the rest of the system never touches OpenAI directly.
How Scoring Works
Scoring is not a single number. Each answer is evaluated across four dimensions:
- Communication: clarity, conciseness, filler word usage
- Structure: STAR method adherence, logical flow
- Specificity: concrete examples, quantifiable results
- Confidence: tone, assertiveness, avoiding hedging language
The scoring system uses a combination of GPT-4's natural language evaluation and structured rubrics. After each session, users see their scores over time on a radar chart, which makes progress visible and motivates continued practice.
Hi there! Want to support me?
Real-Time Sessions
Interview Sparring sessions use a real-time token service for low-latency interactions. The realtime-token.service.ts generates short-lived tokens that the frontend uses to establish a direct connection for streaming AI responses. This avoids the latency of request-response cycles and makes the experience feel like a real conversation.
Auth and Multi-Tenancy
Authentication runs on AWS Cognito with Google OAuth for social login, plus email/password for traditional sign-up. User data is isolated per-user in DynamoDB using partition keys based on userId. The platform supports free tier usage tracking via a dedicated Usage table that tracks monthly session counts per user.
Stripe handles billing with webhook integration for subscription events. The billing service listens for Stripe events and updates user entitlements in DynamoDB, enabling feature gates like unlimited sessions and advanced analytics.
What I Would Do Differently
Building a platform like this solo was ambitious. A few lessons:
- Start with a simpler scoring model and iterate. I over-engineered the scoring dimensions before having enough user data to validate them.
- Resume analysis is computationally expensive. I should have offloaded it to a queue-based worker earlier instead of processing it synchronously.
- Internationalization was a late addition. Adding Spanish, German, French, and Portuguese support after the fact required significant refactoring.
The platform is live and serving users. If you are preparing for interviews, give it a try — the first session is free.