A broker in Jaipur once told me, with complete sincerity, that his CRM was three phones and a diary. Portal leads on one phone, WhatsApp on another, and site visits scribbled in the diary. The week before, a buyer with an ₹80-lakh budget had gone cold — not because he found a better flat, but because the follow-up lived on the phone that was charging at home.
I’m living inside this problem right now — I’m building a real estate portal for Jaipur, and every design decision below is one I’m actually making: how to model a buyer’s requirement, where portal leads land, what happens when the same buyer inquires twice. So when I explain how to build a real estate CRM, this isn’t theory — it’s the working notes.
One thing before we start: the general foundations — the four-table core, the pipeline state machine, buy-vs-build — are in my custom CRM development guide. This post is about what real estate adds on top.
Understand what makes real estate different
A generic CRM assumes a deal is one buyer, one product, a few weeks. Real estate breaks all three assumptions at once:
- One buyer, many properties. A buyer isn’t attached to a listing — they’re attached to a requirement (“3BHK, Vaishali Nagar or nearby, under 90 lakhs, ready to move”), and you evaluate many listings against it.
- The cycle is months, not days. People buy homes slowly. A CRM that only handles hot leads quietly loses the 60% who buy in month three.
- The pipeline has a physical heartbeat: the site visit. Nothing predicts closure like a completed visit. The whole system should bend around getting one scheduled and following it up.
- Leads arrive from chaos. Portals (99acres, MagicBricks, your own site), WhatsApp, hoardings with a phone number, walk-ins, and referrals — all for the same buyer, often in the same week.
Get these four into the architecture and the rest is engineering. Miss them and you’ve built a contact list with extra steps.
Model buyer requirements as data, not notes
The single most important schema decision: the buyer’s requirement is a structured, queryable entity — never a free-text note. The moment “3BHK under 90L in Vaishali Nagar” is a sentence in a notes field, matching becomes a human rereading notes, and the CRM’s best feature dies.
-- On top of the CRM core (contacts, leads, activities) real estate adds:
CREATE TABLE listings (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
purpose text NOT NULL, -- 'sale' | 'rent'
property_type text NOT NULL, -- 'flat' | 'house' | 'plot' | 'commercial'
bhk int,
locality text NOT NULL,
price numeric NOT NULL,
status text NOT NULL DEFAULT 'active', -- 'active' | 'sold' | 'withdrawn'
attrs jsonb, -- furnishing, floor, facing, age…
created_at timestamptz NOT NULL DEFAULT now()
);
CREATE TABLE requirements (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
lead_id uuid NOT NULL REFERENCES leads(id),
purpose text NOT NULL,
property_type text NOT NULL,
bhk_min int,
budget numrange NOT NULL, -- Postgres range type: '[6000000,9000000]'
localities text[] NOT NULL, -- 'Vaishali Nagar', 'Jhotwara'…
timeline text, -- 'immediate' | '3-months' | 'exploring'
created_at timestamptz NOT NULL DEFAULT now()
);
CREATE INDEX idx_req_localities ON requirements USING gin (localities);Notice the numrange for budget and the text[] for localities — Postgres gives you honest range and array queries out of the box, so “find every buyer whose budget covers this price and whose localities include this one” is a single indexed query, not an application-side loop.
The common mistake here is over-modeling on day one: thirty columns for facing, vastu, floor preference, parking. Keep the matchable fields structured (purpose, type, BHK, budget, locality, timeline) and push the soft preferences to jsonb until matching on them proves necessary.
Build matching — it’s the feature that earns the name
Here’s the moment a real estate CRM becomes worth building: a new listing goes live, and within a minute every agent knows which of their open buyers it fits. Buyers stop being rows; they become demand you can act on. The query is almost embarrassingly simple once requirements are structured:
-- New listing just went active — which open buyers does it fit?
SELECT l.id AS lead_id, ct.full_name, ct.phone, r.timeline
FROM requirements r
JOIN leads l ON l.id = r.lead_id AND l.stage NOT IN ('closed-won','closed-lost')
JOIN contacts ct ON ct.id = l.contact_id
WHERE r.purpose = $1 -- listing.purpose
AND r.property_type = $2 -- listing.property_type
AND (r.bhk_min IS NULL OR r.bhk_min <= $3)
AND r.budget @> $4::numeric -- budget range contains listing price
AND r.localities && $5::text[] -- localities overlap
ORDER BY (r.timeline = 'immediate') DESC, l.created_at;Run it on listing creation, drop the results into each agent’s queue as a task, and log the shortlist share as an activity. The reverse direction matters too — when a requirement is captured, generate the buyer’s first shortlist on the spot, because speed to first shortlist is real estate’s version of speed-to-lead.
Design the pipeline around the site visit
Every stage in a real estate pipeline is either before the visit (and exists to get one scheduled) or after it (and exists to convert it). That framing gives you the stage flow almost for free:
new → contacted → requirements captured → shortlist shared → visit scheduled → visited → negotiation → token → closed won / lost
Enforce it as a state machine — only explicit transitions, each one logged as an activity (the mechanics are in the custom CRM guide). What the state machine buys you here specifically:
- The two metrics that run a brokerage — inquiry-to-visit rate and visit-to-close rate — fall straight out of transition logs. No spreadsheet archaeology.
- Visit discipline — a lead can’t reach
visitedwithout a scheduled visit activity, so “did anyone actually take them to the site?” is never a mystery. - Lost isn’t final — allow
lost → contacted. Property buyers resurface after three months constantly; a pipeline that can’t re-open a lead throws that demand away.
And because the cycle is long, follow-ups must be system-owned, not memory-owned: every stage carries a next-action date, and a lead with no future action is, by definition, leaking.
Capture every channel into one deduplicated queue
The broker with three phones wasn’t disorganized — he had three lead channels and no convergence point. Your intake layer is that convergence point, and two rules are non-negotiable for it:
- Every intake endpoint is idempotent. Portals re-send webhooks; email parsers re-run. Without an idempotency key you create duplicate leads, two agents call the same buyer, and your brokerage looks exactly as chaotic as the diary it replaced.
- The phone number is the identity key. Normalize to E.164 at the door. The same buyer will inquire on your portal listing on Monday and call the hoarding number on Saturday — that’s one lead with two source activities, not two leads.
I’ve written up the retry-safety pattern properly in Idempotent APIs & Webhooks: How to Make Retries Safe — real estate portals will exercise it weekly.
If your CRM serves many brokerages rather than one, tenancy is a day-one decision, not a retrofit — the trade-offs are in shared-schema vs schema-per-tenant, and I compare them in the multi-tenant post linked below.
Scope the MVP ruthlessly
Real estate software has infinite tempting features — valuation models, 3D tours, EMI calculators, AI descriptions. None of them save the ₹80-lakh buyer whose follow-up got forgotten. Version one is:
- Capture — every channel into one queue, deduplicated by phone, source recorded.
- Requirements — structured capture on first contact, matchable from day one.
- Matching + shortlist — new listing alerts open buyers; new requirement gets an instant shortlist.
- Visit workflow — schedule, remind, mark done, capture the outcome as an activity.
- Next-action dates — so a months-long pipeline can’t silently leak.
Everything else waits for the core to be trusted. The discipline to cut is a product skill — I wrote about building it in Ship the MVP, Not the Dream, and the tenancy decision in Multi-Tenant SaaS Data Isolation.
The takeaway
Building a real estate CRM in 2026 is not about exotic tech — it’s about modeling the domain honestly. Make buyer requirements structured and queryable, point the whole pipeline at the site visit, let matching turn your buyer list into live demand, and force every chaotic channel through one idempotent, phone-keyed intake. That’s the system that remembers the buyer in month three — long after the diary would have forgotten him.
A real estate CRM has one job: make sure the buyer who inquired in January still gets the right call in March. Requirements as data, visits as the heartbeat, follow-ups owned by the system — that’s the whole game.
If you’re starting from zero, read the custom CRM development guide first for the core model — or say hello via the contact page and tell me what you’re building.