HouseMaster
HouseMaster is a real estate marketplace for the Greek market, with more than 100,000 properties for sale and rent. Since December 2025 I've been the Technical Lead of the team that builds it, across three codebases: the backend, an ingestion service, and a frontend in Greek and English. HouseMaster was also one of the 21 companies selected for the Greek government-backed OpenAI accelerator.

Everything below is the work of that team. Dimitris K. set up and maintains the DevOps side, the Kubernetes cluster and everything that deploys to it, and Manos N. implemented the frontend. Throughout, I've worked closely with our CEO, Marietta L., and with our support specialist, Christina L.
The backend alone has around 300 endpoints across 30 routers, 39 tables, 105 database migrations and about 4,000 tests, with another 374 in the ingestion service, and it serves four kinds of user: people looking for a home, private owners, agents and agencies, and the HouseMaster team.
What It Does
People search by map, by area or by radius and filter on almost everything a listing records: price, size, rooms, floor, year built, heating, parking, amenities, views and more. They can save searches and get emailed when new matches or price drops appear, daily or weekly and outside quiet hours, keep favourites, and contact the agent from any listing, with every inquiry tracked from first contact to the agent's pipeline. A mortgage affordability calculator and paid services (loans, legal and technical checks, valuations) sit alongside the listings.
Private owners publish through a step-by-step wizard that adapts to the property type, from a flat to a plot, a shop or a hotel. Agents get their own dashboard with their listings, an inquiry pipeline, their team and buyer requirements that are matched against new listings. Tenants can pay a rent deposit online through Stripe Connect.
Agencies can also subscribe to a price check ("Έλεγχος τιμών") built on the nightly duplicate grouping. It shows where the same property is listed by other agencies at a different price, from a snapshot taken every night, with a preview for agencies that haven't subscribed yet and an email digest of the 5 biggest gaps. It's sold in three plans by agency size, through Stripe.
The admin side has around 90 endpoints of its own, for reviewing listings, agencies and agents, duplicate groups, data-quality reports, CRM providers, ranking settings, SEO pages and audit logs.
Search
Search runs on PostgreSQL with PostGIS. A map view is a bounding-box query served by a spatial index, a radius search uses distance on the globe, and an area search expands to every neighbourhood and sublocation below it. Location autocomplete is our own endpoint, so typing an address costs nothing in Google fees.
Results are ranked. Ranking considers a listing's quality, its freshness, how people respond to it, its price against the area and recent price drops, and it keeps results varied across agencies. Ranked results are cached in Redis.
Each API worker limits how many searches it runs at once and turns away a request it can't start quickly, every query has a deadline, and result counts are capped. Fixing the map query's index cut its p95 by more than half, and caching the ranking's behaviour scores cut the p95 of search by more than 40%.

Listings, Ingestion and Duplicates
Agencies' CRM systems push their listings to a batch endpoint with their own API key. Each property in a batch is written in its own database savepoint, so one bad record doesn't fail the rest, and the response returns per-item errors plus data-quality warnings, for example a property marked as new construction whose build year is decades old.
Every listing is matched to a three-level location tree (prefecture, neighbourhood and about 15,000 sublocations), using neighbourhood boundaries where they exist and the nearest centre otherwise, with a confidence score that feeds an admin report. The public map shows a slightly offset position, not the exact address, and the ingestion service enriches each area with nearby points of interest from Google Places on a fixed nightly budget.
The same flat is often listed by several agencies, so the ingestion service groups duplicates every night. Matching considers each listing's address, attributes, photos and location, with safeguards so that a doubtful group is dropped before anything is written. Processing the listings area by area took the job from running out of memory to comparing 15.6 million pairs in about 2 minutes.
AI
The AI assistant lets logged-in users describe the home they want by text or by voice. It's an agent with 8 tools (location lookup, search, listing details, map, favourites and saved searches) that call the same search the rest of the site uses, and voice runs over OpenAI's Realtime API through WebRTC, with the server only minting a short-lived session. It sits behind a feature flag and a daily limit per user.
For people publishing a listing, a vision model reads an uploaded energy certificate, as photos or a PDF, and fills in the energy fields, and another model suggests a description from the property's attributes, which the owner can edit.
Architecture
The backend is FastAPI and the frontend is Next.js. Everything runs on AWS, in Kubernetes (EKS) deployed with Helm. PostGIS keeps every geographic query inside PostgreSQL next to the listing data, instead of syncing a separate search engine that could drift from it, and Redis holds the cached search windows, the behaviour-score snapshot and the job queues. Property photos are uploaded to S3 and served through CloudFront. Sign-in (email codes and Google) goes through the API to Supabase Auth, payments through Stripe and email through SendGrid.
Kubernetes, set up and maintained by Dimitris K., runs the API and the jobs around it. The API scales on CPU and memory, with a disruption budget that keeps it serving during node changes, and CronJobs on the same image send notifications every hour, refresh the ranking scores every 15 minutes and take nightly price snapshots after the duplicate run. The ingestion service is its own worker on an ARQ queue, so photo processing and duplicate grouping never compete with user traffic.
Migrations run when a pod starts, with a short lock timeout, so a migration that can't get its lock gives up before the readers behind it start failing. CI runs the test suite with a check that migrations have a single head, a secret scan with gitleaks and a lint of the Helm chart against the staging and production values, and every merge to main deploys. Logfire traces every request and query, and PostHog receives server-side events and serves the feature flags.
See the full project at housemaster.gr.