Skip to content
All projects
AI

ATS Résumé Validator

Real-time résumé scoring against a job description, with country-specific rewrites.

Role
Architect and full-stack developer
Year
2026

Source is in a private repository; architecture walkthrough available on request.

Illustration of a résumé beside a 92 per cent ATS match score and résumé format options

What it is

Upload a résumé and a job description and get an ATS compatibility score from 0 to 100 with sub-scores, weak areas and fixes, streamed live as the analysis runs. The same pipeline regenerates the résumé in US, UK/Ireland, Europass or German Lebenslauf format.

The problem

LLM analysis takes tens of seconds and sometimes returns malformed output. The product needed instant feedback in the browser, output that is always valid, and an architecture that could grow from one server to many.

Architecture

Requests flow left to right. Hover a component for its role.

ATS Résumé Validator architecturepublish jobresultSSE progressscrapeReact SPA: static buildReact SPAnginx: reverse proxy, SSE unbufferednginxSpring Boot API: auth, files, orchestrationSpring Boot APIPostgreSQL: jobs, JSONB resultsPostgreSQLS3 or filesystem: artifacts with expiryS3 or filesystemRabbitMQ: ai.jobs, ai.results, DLQsRabbitMQPython AI worker: extract, LLM, validate, repairPython AI workerClaude or OpenAI: structured outputClaude or OpenAIEmail and web pushEmail and web pushPrometheus: metrics scrapePrometheus
Solid line: synchronous callDashed line: through a queueDashed box: external or infrastructure
  • React SPA client, static build
  • nginx edge, reverse proxy, SSE unbuffered
  • Spring Boot API service, auth, files, orchestration
  • PostgreSQL data, jobs, JSONB results
  • S3 or filesystem data, artifacts with expiry
  • RabbitMQ queue, ai.jobs, ai.results, DLQs
  • Python AI worker worker, extract, LLM, validate, repair
  • Claude or OpenAI ai, structured output
  • Email and web push external
  • Prometheus infrastructure, metrics scrape

Key decisions

  • Contracts before code

    The ERD, RabbitMQ message contracts, versioned LLM JSON Schema and OpenAPI surface were fixed in the design spec before implementation. 41 specs and plans drove the build in vertical slices.

  • The worker never talks to the browser

    The Python worker publishes to ai.results; Spring consumes it, validates and persists it, then emits the SSE event. One component owns client state, and dead-letter queues catch poison messages.

  • Validate, then repair once

    LLM output is checked against a versioned JSON Schema and gets exactly one repair retry before the job fails cleanly. Results are stored as JSONB with a schema version so old analyses still render.

  • Seams for scale, not premature scale

    SSE fan-out is an in-process registry for one instance, with a documented topic-exchange seam for many. Rate limits use in-memory Bucket4j with a Redis seam.

Highlights

  • 465 commits delivered from 41 written specs and implementation plans.
  • Liveness and readiness probes and Prometheus metrics on the API, worker and AI health service.
  • Uploads validated for type, size and page count, stored behind a storage abstraction with automatic expiry.
  • Jenkins and Bitbucket pipelines, a scripted Ubuntu setup and a release script with rollback.

Stack

Spring BootJava 17PostgreSQLRabbitMQPythonFastAPIAnthropic ClaudeOpenAIReact 19TypeScriptViteMinIO / S3PrometheusJenkinsTestcontainers