How a Job Search Engine Works Across Millions of Vacancies Without Middlemen
Job hunting at foreign or large IT companies often turns into a routine with unpleasant surprises. You find an interesting position on an aggregator, click the link, and the vacancy was closed a month ago. Or you stumble upon endless copies of the same listing from recruiting agencies that don't even name the end employer.

The freehire project solves this problem with a straightforward technical approach: it parses data directly from applicant tracking systems (ATS), bypassing intermediaries. The database contains over 3.3 million active vacancies from nearly 300,000 companies. The entire stack is open under the MIT license, including data collectors, web interface, search engine, and API.
Where the data comes from
Most tech companies publish vacancies through specialized services like Greenhouse, Lever, Workday, Ashby, or iCIMS. The creators of freehire wrote adapters for 92 such platforms, and also connected about a hundred third-party job boards and direct feeds from large corporations.
The pipeline works as follows:
- A worker crawls job boards and reads fresh vacancies. Adding a company usually takes one line in a YAML file, specifying the name and ID in the ATS.
- Data is normalized into a unified format. If one vacancy is published on multiple platforms, the system merges duplicates by a stable key.
- Filters for grades, salaries, locations, and tech stack are built from strict dictionaries. There are no unreliable heuristics here—the system doesn't try to guess data at random.
- A separate worker downloads the actual application form from the target ATS, preserving the original field structure.
What's inside besides the vacancy catalog
Search is just the storefront. Around the vacancy database, developers built a full-featured candidate workspace.
Resume generator and match checking
The repository includes a resume builder that renders PDF files optimized for automated ATS parsing. The system matches job requirements against your experience and calculates deterministic compatibility scoring. When connected to a language model, it provides targeted resume adjustments for specific applications without fabricating experience.
Response tracker with incoming mail
After submitting an application, tracking continues on a Kanban board with status updates. An integrated email gateway connects recruiter responses to specific application cards, keeping correspondence organized rather than lost in a general inbox.
Assistant and browser extension
A Chrome sidebar extension has been developed. When you open a job page on any site, the plugin reads the page text, cross-references it with your profile, and fills out the application form for you. For those who prefer working through LLM clients like Claude Desktop, the authors provide a separate MCP server.
Architecture and tech stack
The codebase is written in Go using the Fiber v2 web framework. Architecturally, the backend is clearly separated: the API server handles client requests exclusively, while all background work is moved to separate one-off workers. These are convenient to run via cron or inside queues.
cmd/ Точки входа: HTTP-сервер и консольные воркеры
sources/ Файлы конфигурации источников вакансий (YAML)
migrations/ Схема PostgreSQL для sqlc и initdb
web/ Интерфейс на SvelteKit 2
internal/ Внутренние пакеты предметной области
sources/ Адаптеры под конкретные ATS (Workday, Lever, etc.)
pipeline/ Пайплайн сбора, валидации и дедупликации
cv/ cvedit/ Генерация структурированных резюме в PDF
inbox/ Обработка и связывание почты рекрутеров
For storage and fast search, a combination of components is used:
- PostgreSQL with the pgvector extension stores main entities and vector embeddings for semantic search.
- sqlc generates type-safe code for working with the database from plain SQL queries—no ORM is used.
- Meilisearch handles full-text search and instant faceted filtering.
- SvelteKit 2 (on Svelte 5 runes) and Tailwind 4 form the fast SSR frontend.
- Redis and MinIO cover caching, request rate limiting, and object storage for files.
Quick start and working with the API
You can spin up a local copy of the service along with all dependencies via Docker:
make up
The command will start the database, search engine, API, and web interface on port 8080. You can check availability with a simple curl request:
curl localhost:8080/health
curl localhost:8080/api/v1/jobs
By the way, the project's public API is available without keys or authorization. If you need access to fresh vacancies for your bot or pet project, just hit the endpoint https://freehire.me/api/v1/jobs. All responses are returned in predictable JSON format with structured metadata and pagination.
To run data collectors, console commands in cmd/ are used:
# Обход конкретного каталога ATS
go run ./cmd/ingest sources/greenhouse.yml
# Сброс очереди индексации в Meilisearch
go run ./cmd/search-drain
# Извлечение вакансий из Telegram-каналов
go run ./cmd/tg-extract
Who is this project for
The repository will be useful in three cases:
- You're looking for a job at international companies and are tired of low-quality aggregators. The web version gives direct links to employer ATS systems without intrusive middlemen.
- You want to build your own aggregator, Telegram channel with vacancies, or bot. The open adapters to 92 ATS systems save hundreds of hours on writing parsers.
- You're interested in an example of a mature Go project without overloaded ORMs, with strict SQL typing, separation into independent workers, and integration with a modern search engine.
The project looks mature, and its openness gives any developer the opportunity to submit a pull request with a new company in one YAML line. You can try the service live on the project website or by deploying containers on your own server.
Related projects