Core Entities
Property: (property_id, listing_type=SALE|RENT, status=ACTIVE|PENDING|SOLD|WITHDRAWN, address, geo_point, price_cents, bedrooms, bathrooms, sqft, year_built, property_type=HOUSE|CONDO|APARTMENT|LAND, description, agent_id, created_at). PropertyImage: (image_id, property_id, url, is_primary, order). Agent: (agent_id, name, license_number, brokerage, phone, email, service_areas[], avg_rating). Lead: (lead_id, property_id, user_id, agent_id, message, status=NEW|CONTACTED|TOURED|OFFER|CLOSED|LOST, created_at). SavedSearch: (search_id, user_id, filters, alert_frequency=INSTANT|DAILY|WEEKLY).
Property Search
Search combines location, price, and attribute filters. Use Elasticsearch: index properties with geo_point for proximity search, and all filterable attributes (price, bedrooms, sqft, property_type, status). Search query: geo_distance filter (within 5 miles of a point or within a polygon), price range, bedroom/bathroom minimum, property_type IN (…), status=ACTIVE. Polygon search: user draws a boundary on the map; search returns properties within the polygon. Elasticsearch supports geo_shape queries for polygon containment. Sorting: by price, newest listed, distance. Ranking: promoted listings (paid) appear first within a relevance band. Text search on description uses standard Elasticsearch text matching.
Saved Searches and Alerts
A user saves a search with their filter criteria. When a new property is listed that matches a saved search: notify the user. Implementation: on property INSERT or status change to ACTIVE: publish a PropertyListed event to Kafka. A matching service consumes the event. For each active SavedSearch: evaluate the property against the search filters. If it matches: create a notification. Batch processing: for daily/weekly alerts, accumulate matches in a pending_alerts table. A scheduled job sends digest emails for DAILY/WEEKLY users at 8am. For INSTANT alerts: send push notification and email immediately. Index saved searches by zip code and price range for efficient matching (avoid scanning all saved searches for every new listing).
Mortgage Calculator
Monthly payment formula: M = P * [r(1+r)^n] / [(1+r)^n – 1]. Where P = principal (loan amount), r = monthly interest rate (annual_rate / 12), n = number of payments (loan_term_years * 12). Implement server-side to ensure consistency across platforms. API endpoint: POST /mortgage/calculate with {price, down_payment, loan_term_years, annual_rate}. Returns: monthly_payment, total_payment, total_interest, amortization_schedule (month-by-month breakdown). Cache results (same inputs = same output). Show affordability: if monthly_payment > user_monthly_income * 0.28 (28% rule): flag as potentially unaffordable. This is the frontend feature that drives user engagement and keeps users on the platform.
Agent Matching
Match a buyer/seller with an appropriate agent. Matching criteria: service area (agent serves zip codes where the property is), specialization (buyer vs seller agent, luxury, commercial), availability (agent has capacity — track active leads per agent), rating (avg rating from past clients), experience (years licensed, transaction volume). Scoring: weighted score = 0.4 * rating + 0.3 * area_match + 0.2 * specialization_match + 0.1 * availability. Return top-3 agents. Lead routing: when a user submits a contact form: create a Lead and route to the matched agent. Auto-assign if only one agent matches. Track lead response time per agent (agents who respond slowly get lower matching scores). Marketplace: allow users to browse and choose their own agent (agent profiles with reviews, past listings).
Virtual Tours and Media
Images: upload to S3 via presigned URL (client uploads directly, bypassing the server). Store image metadata (url, order, is_primary) in PropertyImage table. Generate thumbnails (300×200, 800×600) via a Lambda function triggered on S3 upload. Serve via CDN (CloudFront). Virtual tours: embed 3D tours (Matterport) or 360-degree photos as iframes. Store the tour embed URL on the property record. Video tours: upload video to S3, transcode via AWS MediaConvert to HLS format for adaptive streaming. Property photos must be validated (no text, correct orientation) — use AWS Rekognition or Google Vision API for content moderation on upload.
Interview Tips
- Polygon search is the differentiating feature of modern real estate platforms (Zillow’s “draw your search area”). Elasticsearch geo_shape or PostGIS for polygon containment.
- Price history: store a PriceHistory table (property_id, price_cents, changed_at). Display price changes on the listing (“Price reduced 3 days ago”). Important for buyer decision-making.
- Days on market (DOM): created_at to current date for active listings. Track separately for re-listed properties (new listing = reset DOM).
{
“@context”: “https://schema.org”,
“@type”: “FAQPage”,
“mainEntity”: [
{
“@type”: “Question”,
“name”: “How do you implement polygon-based property search for a map interface?”,
“acceptedAnswer”: {
“@type”: “Answer”,
“text”: “Users draw a polygon on the map to search within a custom boundary. Implementation: the frontend sends the polygon coordinates (list of lat/lng pairs) as a GeoJSON Polygon. The backend executes a geospatial query: Elasticsearch geo_shape query (geo_shape field on the property with a geo_shape filter of type ‘within’). PostgreSQL + PostGIS: ST_Within(property.location, ST_GeomFromGeoJSON(:polygon)). Index: in Elasticsearch, index property coordinates as a geo_point. In PostGIS, create a spatial index (GiST) on the geometry column. Performance: spatial indexes reduce full-table scans. For Elasticsearch, the geo_shape query is slower than geo_distance — use it only when the user explicitly draws a polygon. For simple radius searches, use the faster geo_distance filter.”
}
},
{
“@type”: “Question”,
“name”: “How do you implement property listing alerts for saved searches?”,
“acceptedAnswer”: {
“@type”: “Answer”,
“text”: “When a user saves a search (filters: 3-bed, $500K-$800K, San Francisco), they want to be notified when new matching properties are listed. Architecture: on property listing creation or status change to ACTIVE: publish a PropertyListed Kafka event with all property attributes. An alert matching service consumes the event and evaluates it against all active saved searches. Naive: evaluate every saved search for every new listing. Optimized: index saved searches by geo bounding box and price range. For each new listing: find saved searches whose bounding box contains the property and price range overlaps. Evaluate only those (much smaller set). If a match: create a notification record and send via the user’s preferred channel (email, push). Batch alerts: for DAILY frequency users, accumulate matches during the day and send a digest at 8am.”
}
},
{
“@type”: “Question”,
“name”: “How do you calculate mortgage payments and display amortization schedules?”,
“acceptedAnswer”: {
“@type”: “Answer”,
“text”: “Monthly payment formula: M = P * [r(1+r)^n] / [(1+r)^n – 1]. P = loan principal (price – down payment). r = monthly rate = annual_rate / 12. n = total months = years * 12. Example: $500K loan, 7% annual, 30 years. r = 0.07/12 = 0.00583. n = 360. M = 500000 * [0.00583 * (1.00583)^360] / [(1.00583)^360 – 1] = $3,327/month. Amortization schedule: for each month, interest_payment = remaining_balance * r. principal_payment = M – interest_payment. remaining_balance -= principal_payment. Early months are mostly interest; later months are mostly principal. Total interest paid = M * n – P. Display: show total cost of ownership (purchase price + total interest over loan term). This feature drives significant user engagement on real estate platforms.”
}
},
{
“@type”: “Question”,
“name”: “How do you implement agent matching and lead routing?”,
“acceptedAnswer”: {
“@type”: “Answer”,
“text”: “When a buyer clicks ‘Contact Agent’: create a Lead record and route to the best matching agent. Matching algorithm: (1) Geographic eligibility: agent.service_areas must include the property’s zip code. (2) Specialization match: buyer-facing agents for buyer leads; listing agents for seller inquiries. (3) Capacity: count of agent’s active leads in the last 30 days. Prefer agents with fewer active leads (not overloaded). (4) Performance score: weighted average of avg_rating (40%), response time (30%), conversion rate (30%). Score = 0.4*rating + 0.3*(1/avg_response_hours) + 0.3*conversion_rate. Return top-3 agents for the user to choose from. Auto-routing: if the user does not choose within 1 hour, auto-assign to the top scorer. Track lead response time: if the assigned agent does not respond within 24 hours, reassign to next in list.”
}
},
{
“@type”: “Question”,
“name”: “How would you design the search ranking for property listings?”,
“acceptedAnswer”: {
“@type”: “Answer”,
“text”: “Ranking factors for property search results: (1) Relevance to query filters (exact matches rank higher than approximate). (2) Listing freshness: newer listings rank higher. (3) Premium placement: agents can pay to boost listings within a relevance band. (4) Engagement signals: listings with more saves and contact form submissions signal quality — rank higher. (5) Completeness: listings with photos, virtual tours, and complete descriptions rank higher than sparse listings. (6) Price accuracy: listings priced within market range (validated against comps) rank higher than potentially mispriced outliers. Implementation: Elasticsearch function_score query. Combine BM25 text relevance with multiplicative boost factors (freshness_boost, premium_boost, engagement_boost). Premium boost cannot move a low-relevance listing above a highly-relevant one (cap premium boost at 1.5x relevance score).”
}
}
]
}
Asked at: Airbnb Interview Guide
Asked at: Stripe Interview Guide
Asked at: Uber Interview Guide
Asked at: Lyft Interview Guide