Completed case study
Virtual ClientMulti-Tenant AI Voice Coaching Platform
Teams rehearse live conversations against AI personas and get rubric-scored feedback.
- Role
Lead Engineer
- Stack
- React
- Vite
- TypeScript
- Express
- Firebase
- Firestore
- Client
Robbie Boyle
EdTech / Corporate Training
Nov 2025- Team
Team of 5 developers

01The challenge
The platform served multiple organisations from shared Firestore collections, so a single mis-scoped security rule could expose one client's practice sessions to another. Tenancy could not be verified by reading the rules alone.
Scope: Multi-tenancy hardening, security-rule migration, voice pipeline integration, evaluation scoring
Key features
- Real-time voice roleplay against configurable AI personas (Gemini Live)
- Rubric-scored feedback generated by OpenAI and Anthropic models
- Multi-tenant organisation isolation across eight Firestore collections
- Two-step security-rule migration performed with zero downtime
- 370+ security tests plus an emulator-driven test harness
- Team and per-user session history with progress tracking




Overview
A B2B SaaS platform for real-time voice-AI coaching. Teams practise live conversations against AI personas powered by Gemini Live, then receive rubric-scored feedback generated with OpenAI and Anthropic models. Running in multi-org production with roughly 2,500 practice sessions delivered.
- ~2,500
- Practice sessionsDelivered across organisations in production
- 370+
- Security testsGuarding tenant isolation in CI
- 8
- Collections hardenedMigrated to strict tenant-scoped rules
02The approach
Migrated eight critical collections to strict tenant-scoped rules in two safe steps so live traffic was never broken, then locked the result behind 370+ security tests and an emulator-driven harness that fails CI on any misconfiguration before it can reach production.
Built to a standard
- Multi-tenant
- Production
- Test-hardened
03Problems solved
Problem
Providing low‑latency, two‑way voice interaction for dozens of simultaneous learners while keeping costs under control.
Solution
Implemented a Vercel Edge Function that acts as a thin proxy to the Gemini Live API. The function streams audio chunks directly to the client, avoiding a full round‑trip through the backend. Tenant IDs are attached to each request and used to select the appropriate API credential stored in Firebase Remote Config. To prevent overload, a simple token bucket limits concurrent streams per tenant, and excess connections receive a polite retry response. This design keeps latency under 300 ms for 95 % of sessions and scales with Vercel’s automatic edge replication.
Problem
Ensuring strict data isolation between organizations in a shared Firestore database.
Solution
Created a top‑level collection named "tenants" where each tenant ID hosts its own sub‑collections for users, sessions, and rubrics. Security rules check the requester's custom claim against the tenant ID in the document path, rejecting any cross‑tenant access. For writes that affect many documents (e.g., bulk rubric updates) used batched writes limited to 500 operations per batch to stay within Firestore limits. Added composite indexes for common queries like "sessions where score > 80 and tenant = X" to keep query times under 200 ms.
Problem
Scoring learner responses against complex rubrics without slowing down the user experience.
Solution
Moved the scoring logic to a Cloud Function triggered by Firestore writes. The function reads the rubric definition from a cached collection (stored in Firestore with a 5‑minute TTL) and runs the evaluation in parallel using Node 20 worker threads. Results are written back to the session document, and a Pub/Sub topic notifies the frontend via TanStack Query's subscription hook. This off‑loads heavy computation, reduces front‑end latency to under 150 ms, and keeps the function cost under $0.02 per thousand evaluations.
Problem
Rendering dashboards that show performance metrics for thousands of learners without freezing the browser.
Solution
Adopted TanStack Query with infinite scrolling and server‑side pagination for the learner list. Aggregated cohort statistics (average score, completion rate) are pre‑computed in a nightly Cloud Function and stored in a separate "metrics" collection. The dashboard fetches only the aggregated numbers and the current page of learners, then feeds the data into Recharts components that are lazy‑loaded with Vite's dynamic import. This approach caps initial bundle size at 120 KB and keeps frame rates above 55 fps on typical laptops.
Need something like this?
I build products like Virtual Client for clients worldwide
The closest package is AI Agent SaaS Products: fixed price, fixed scope, delivered remotely. Tell me what you are building and I will say which tier fits.
More work
Related projects

- Developer Tools
- 2026
Nestor — NestJS Mentor for VS Code
Hover any NestJS symbol for the official docs, and hover your own classes to learn which design pattern they follow

- Founder Community / SaaS
- 2026
Founders — Reputation Economy for Founders
Credit-metered peer feedback, AI-scored reviews, and launches with public show-up rates.

- HealthTech / Clinical Software
- 2026
MedScribe — Prescription Platform for Doctors
Prescriptions your patients can actually read.