SYSTEM_DESIGN

System Design: Rental Listing Platform

Design a rental listing platform like Apartments.com supporting landlord listing management, tenant search, virtual tours, and application workflow. Covers geo-search, listing freshness, fraud prevention, and lead routing.

12 min readUpdated Jan 15, 2025
system-designreal-estaterentallistingsgeo-searchfraud-prevention

Requirements

Functional Requirements:

  • Landlords post rental listings with photos, virtual tours, amenities, and availability dates
  • Tenants search by location, price, bed/bath, pet policy, and move-in date
  • Saved searches with email/push alerts for new matching listings
  • Lead routing: tenant inquiry goes to the listing's contact (landlord or property manager)
  • Online application submission with supporting document upload
  • Listing freshness: landlords mark units as rented; stale listings auto-expire after configurable period

Non-Functional Requirements:

  • Geo-search returning results within 500ms for a metro-area radius query
  • Listing photos served globally via CDN with <200ms latency
  • Fraud detection: identify and remove fake listings before they receive tenant inquiries
  • 99.9% uptime; downtime causes missed leads for landlords paying for premium placement
  • GDPR/CCPA compliance for tenant and landlord PII

Scale Estimation

For a national platform: 15M active rental units, 5M new listings/year = ~14k/day. Daily active tenants: 5M × 10 searches each = 50M searches/day = ~579/second average, 5x peak = ~2,895/second. Photos: 5M listings × 15 photos = 75M photo objects with 3 resolutions = 225M image objects. Leads: 5M listings × 2 inquiries/month = 10M/month = ~4/second. Saved search alerts: 10M saved searches × 10% match rate on new listings = 1M notifications/day.

High-Level Architecture

The platform has three main planes: a Listing Management Plane (landlord-facing), a Discovery Plane (tenant-facing search and browse), and a Lead/Application Plane (inquiry and application flow). These share a common listing database but have separate API surfaces and caching strategies — the discovery plane is heavily read-optimized while the listing management plane requires consistent reads for landlords managing their own listings.

Listing freshness is enforced by an Expiry Service. Each listing has an auto_expire_at timestamp set at creation (default 30 days, configurable). Landlords receive reminder notifications at 7 days, 3 days, and 1 day before expiry with a one-click renewal. The Expiry Service runs a nightly job removing expired listings from the search index and search APIs. Listings removed from search are retained in a soft-deleted state for 90 days for landlord reference.

Fraud detection runs on every new listing submission. A scoring model evaluates: duplicate photo detection (perceptual hash matching against known-fraudulent listings), price anomaly detection (price vs. area median), contact phone/email reputation scoring, and landlord account age/history. High-risk listings are held for manual review; clear fraud is automatically rejected with a notification to the submitter.

Core Components

Listing Ingestion & Fraud Detection Service

Handles listing creation with synchronous fraud scoring before publication. Photo uploads are processed asynchronously (resize to 3 sizes, store in S3) but fraud scoring runs synchronously on submission. The fraud model returns a risk score and flag reason; listings above the threshold enter a pending_review status and are not visible in search until cleared. Photo deduplication uses perceptual hashing (pHash) against a blocklist of known fraudulent listing images — an O(1) Redis lookup on the hash.

Geo-Search Service

Elasticsearch cluster with geo_point fields enabling radius, bounding-box, and polygon searches. Listings are indexed with all filterable attributes. A custom similarity plugin implements listing freshness scoring — listings updated recently rank higher than stale listings at equal relevance. "Best match" ranking combines: text match (if search has keywords), distance from search center, price-per-sqft vs. area median (value scoring), and freshness. The geo-search service returns listing IDs; a separate hydration step fetches full listing data from Redis cache.

Lead Routing & Application Service

When a tenant submits an inquiry, the Lead Router determines the correct contact: individual landlord (email + phone), property management company (routes to available leasing agent), or large apartment community (routes to their CRM via webhook). Lead delivery is attempted via multiple channels simultaneously (email, SMS, in-app notification) with read-receipt tracking. Applications include a document upload flow similar to the mortgage platform but lighter-weight; submitted applications are visible to the landlord in their management dashboard.

Database Design

Listings: listing_id UUID, landlord_id, property_id, address, geo POINT, unit_number, bedrooms, bathrooms, rent_price, available_date, status ENUM(active, rented, expired, pending_review, rejected), auto_expire_at, created_at, last_renewed_at. Amenities and pet policy stored as structured JSONB columns. listing_photos (listing_id, s3_keys[], photo_hashes[]). listing_views (listing_id, user_id, viewed_at, source) — analytics table for landlord dashboard.

Leads: leads (lead_id, listing_id, tenant_id, message, contact_email, contact_phone, status ENUM, created_at, responded_at). Applications: applications (app_id, listing_id, tenant_id, status ENUM, submitted_at, documents JSONB). Saved searches: saved_searches (search_id, user_id, criteria JSONB, alert_frequency ENUM, last_alerted_at). A daily job re-runs each saved search against Elasticsearch and queues notifications for new matches.

API Design

POST /api/v1/listings — landlord creates a listing; triggers fraud scoring; returns {listing_id, status}.

GET /api/v1/listings/search?lat=&lon=&radius_km=&min_beds=&max_price=&available_before= — geo-radius search; returns paginated listing summaries.

POST /api/v1/listings/{listingId}/leads — tenant submits an inquiry; triggers lead routing.

PUT /api/v1/listings/{listingId}/mark-rented — landlord marks unit as rented; removes from search index immediately.

Scaling & Bottlenecks

Search is the dominant traffic pattern and must scale to ~3,000 queries/second at peak. The Elasticsearch cluster uses 12 data shards with 2 replicas (36 nodes total in a balanced deployment). Search queries are cached at the API gateway layer for identical query strings with a 60-second TTL — common metro-area searches ("2BR in Brooklyn under $3000") are served from cache without hitting Elasticsearch. Cache key includes all filter parameters but excludes user ID, since search results are not personalized.

Saved search notifications require running millions of searches against the Elasticsearch cluster daily. This is batched into off-peak hours (2-5 AM) with a distributed job scheduler that partitions saved searches across workers. Each worker runs its assigned saved search batch, compares results to the tenant's last-seen listing set, and queues notifications only for genuinely new matches.

Key Trade-offs

  • Stale listing expiry vs. landlord friction: Aggressive auto-expiry keeps the index fresh and improves tenant trust but annoys landlords whose units remain available; a flexible, reminder-based renewal flow with one-click renewal minimizes friction while maintaining freshness.
  • Fraud scoring synchronously vs. asynchronously: Synchronous scoring on submission delays the landlord's listing going live (adds 200-500ms) but prevents fraudulent listings from ever appearing in search; async scoring is faster to publish but requires a brief window where fraudulent listings could be visible.
  • Geo-search granularity: City-level geo filters are fast but imprecise (Brooklyn vs. Manhattan boundary crossing); street-level distance queries are precise but computationally heavier; a two-stage approach (city filter first, distance scoring second) balances both.
  • Direct lead vs. platform-mediated communication: Routing leads directly (giving tenant the landlord's phone number) provides faster communication but removes the platform from the relationship; platform-mediated messaging adds value for both sides (compliance record, review system) but requires platform adoption.

GO DEEPER

Master this topic in our 12-week cohort

Our Advanced System Design cohort covers this and 11 other deep-dive topics with live sessions, assignments, and expert feedback.