
TalentPike
Enterprise AI Recruiting Platform
A multi-tenant, AI-powered Applicant Tracking System built for enterprise recruiting — resume parsing, semantic job matching, explainable candidate ranking, interview intelligence and recruiter analytics, deployed on Azure.
Sub-second
Inference latency
20+ hrs/mo
Manual work saved
Row-level
Tenant isolation
In-house LLM
Data residency
Business challenge
Enterprise recruiting teams drown in unstructured resumes and requisitions. Keyword filters miss qualified candidates, screening is slow and subjective, and every organization needs strict data isolation. Recruiters need ranked, explainable shortlists — not another inbox.
What I built
I architected a multi-tenant ATS where every resume and requisition is parsed into structured entities, embedded into a vector space, and scored against the role using a hybrid of semantic similarity and rule-based signals — each match shipping with a human-readable explanation. Tenancy, RBAC, audit logging and analytics were first-class from day one, and a local LLM (Ollama) kept sensitive parsing in-house.
Why it matters
Enterprises run recruiting across many departments and, in a SaaS context, many customer organizations. That means multi-tenancy, role-based access, audit trails and predictable cost are not optional — they are the price of entry. The platform had to feel like a modern product while satisfying enterprise security and compliance expectations.
How it's designed
Interface
How the intelligence flows
- 01Ingest — normalize PDF/DOCX resumes and job requisitions.
- 02Parse — extract skills, titles, employers and experience with a local LLM (Ollama).
- 03Embed — generate vector embeddings for candidates and roles.
- 04Match — hybrid semantic similarity + structured signals (skills, seniority, recency).
- 05Rank — explainable scoring that returns the 'why' behind each shortlist.
- 06Interview intelligence — structured guides and post-interview summaries.
How data is modeled
- PostgreSQL as the system of record with a tenant_id on every row (row-level multi-tenancy).
- pgvector column storing candidate & role embeddings; HNSW/IVFFlat index for fast similarity search.
- Normalized entities: tenants, users, candidates, jobs, applications, matches, interviews, offers.
- Redis for hot caches, rate limiting and background job queues.
- Append-only audit_log table capturing sensitive candidate-data access.
Key endpoints
/api/resumes/parseParse a resume into structured, tenant-scoped entities./api/jobs/{id}/matchRank candidates for a role with explainable scores./api/candidates/searchSemantic search across the tenant's talent pool./api/interviewsGenerate a structured interview guide for a candidate./api/analytics/funnelRecruiter funnel, source and time-to-hire analytics.Technologies
Key features
- AI resume parsing into structured, searchable profiles.
- Semantic job matching — find candidates by meaning, not keywords.
- Explainable candidate ranking with rationale for each match.
- Interview intelligence — structured guides and summaries.
- Offer management with approval workflows.
- Recruiter analytics — funnel, source and time-to-hire.
- Role-based access control with audit logging, JWT and MFA-ready auth.
Challenges & trade-offs
Tenant isolation at the data layer
Every query, embedding and file had to be provably scoped to a tenant. I used row-level tenancy with enforced tenant_id predicates and per-tenant storage prefixes, verified by automated policy tests.
Explainable AI scoring
A raw similarity score isn't trusted by recruiters. I combined vector similarity with structured signals (skills, seniority, recency) and generated human-readable rationales for each ranking.
Keeping sensitive data in-house
Resumes are sensitive PII. Running parsing on a local LLM (Ollama) meant candidate data never had to leave the environment for third-party inference.
Code snippet
async def score_candidate(candidate: Candidate, role: Role) -> Match:
# Semantic similarity from pgvector (scoped to tenant)
semantic = await vectors.similarity(
candidate.embedding, role.embedding, tenant=role.tenant_id
)
# Structured, explainable signals
signals = {
"skills": skill_overlap(candidate.skills, role.required_skills),
"seniority": seniority_fit(candidate.years, role.level),
"recency": recency_weight(candidate.last_active),
}
score = 0.6 * semantic + 0.4 * weighted(signals)
return Match(
candidate_id=candidate.id,
score=round(score, 3),
rationale=explain(semantic, signals), # human-readable "why"
)How it ships
- Containerized services deployed on Azure with revision-based rollouts.
- Managed PostgreSQL with pgvector for embeddings; Redis for caches and queues.
- Local LLM served via Ollama for private, cost-controlled inference.
- CI/CD pipeline — build, test, scan and deploy on every merge.
Security
- — Row-level multi-tenancy with enforced tenant predicates.
- — JWT authentication, RBAC and MFA-ready flows.
- — Encryption in transit and at rest; per-tenant storage isolation.
- — Append-only audit logging of sensitive candidate-data access.
Scalability
- — Stateless API scales horizontally behind the container platform.
- — Vector index tuned with HNSW/IVFFlat for sub-second search at scale.
- — Async workers offload parsing and embedding from request paths.
- — Redis caching and read replicas protect the primary database.