---
title: Real Estate PropTech on AWS (2026): MLS Ingest, Geo Search, and Image Pipeline Reference Architecture
description: For a regional PropTech platform (~420k listings, 38 MLS connectors), DynamoDB canonical store + OpenSearch geo cut median search latency from 340 ms to 48 ms — image CDN cost −62% with Intelligent-Tiering.
url: https://www.factualminds.com/blog/aws-real-estate-proptech-reference-architecture-2026/
datePublished: 2026-07-06T00:00:00.000Z
dateModified: 2026-07-06T00:00:00.000Z
author: palaniappan-p
category: Cloud Architecture
tags: aws, proptech, real-estate, opensearch, dynamodb, cloudfront, mls, architecture
---

# Real Estate PropTech on AWS (2026): MLS Ingest, Geo Search, and Image Pipeline Reference Architecture

> For a regional PropTech platform (~420k listings, 38 MLS connectors), DynamoDB canonical store + OpenSearch geo cut median search latency from 340 ms to 48 ms — image CDN cost −62% with Intelligent-Tiering.

**Amazon OpenSearch Service** supports **k-NN vectors up to 16,000 dimensions** per field ([vector search docs](https://docs.opensearch.org/latest/search-plugins/vector-search/)) — enough for listing embedding similarity at regional scale. **AWS HealthImaging-scale lesson does not apply here**; PropTech wins on **ingest discipline** and **geo index design**, not petabyte imaging.

This post is the **real estate / PropTech reference architecture** — MLS to mobile map. It is **not** [retail lakehouse analytics](/blog/aws-retail-omnichannel-analytics-lakehouse-2026/), **not** [fintech payments architecture](/blog/building-fintech-applications-on-aws-architecture-patterns/), and **not** the [industry hub FAQ](/industries/aws-real-estate/) alone.

Artifacts: [listing search tier matrix](https://www.factualminds.com/examples/architecture-blog-2026/real-estate-proptech/listing-search-tier-decision-matrix.md), [MLS ingest cost worksheet](https://www.factualminds.com/examples/architecture-blog-2026/real-estate-proptech/mls-ingest-cost-worksheet.csv).

> **Benchmark pattern (not a cited client)** — **Regional PropTech**, **~420k** active listings, **38** MLS connectors, **median search 340 ms**, **image storage $28k/mo** on Standard. Phase 1: **DynamoDB** canonical + **OpenSearch** `geo_point` (**search p95 340 ms → 48 ms**). Phase 2: S3 **Intelligent-Tiering** + CloudFront WebP (**image CDN cost −62%**). No MLS vendor replacement.

## Four lanes — MLS to mobile

| Lane          | Question                       | Default AWS path                              |
| ------------- | ------------------------------ | --------------------------------------------- |
| **Ingest**    | How do feeds land safely?      | Per-connector **Lambda** + **Step Functions** |
| **Canonical** | What is source of truth?       | **DynamoDB** single-table                     |
| **Search**    | How do users query map + text? | **OpenSearch** `geo_point` + optional k-NN    |
| **Media**     | How do photos load fast?       | S3 → **CloudFront** WebP variants             |

**Opinionated take:** **DynamoDB canonical store before OpenSearch cluster.** Teams that index MLS JSON directly into OpenSearch rebuild dedupe logic twice.

## Reference architecture

```
MLS/IDX APIs ──► Lambda connector ──► SQS ──► Normalize ──► DynamoDB (canonical)
                                    │
                                    ├──► OpenSearch (geo_point, facets, k-NN)
                                    │
Images ──► S3 ingest ──► Lambda resize (WebP) ──► CloudFront ──► mobile/web
                                    │
Optional ──► Rekognition labels ──► listing enrichment
Optional ──► Bedrock ──► listing copy (human review gate)
```

### Ingest — one connector, one failure domain

Per feed:

- Independent Lambda + DLQ — one MLS outage does not poison others
- Normalize to unified schema; key `(marketId, listingId)` + `addressHash` for cross-MLS dedupe
- Fill [mls-ingest-cost-worksheet.csv](https://www.factualminds.com/examples/architecture-blog-2026/real-estate-proptech/mls-ingest-cost-worksheet.csv) after pilot week in Cost Explorer

**Do not** schedule full image re-sync 12×/day on large feeds — delta + ETag only.

### Canonical — DynamoDB single-table

See [DynamoDB single-table SaaS patterns](/blog/dynamodb-single-table-design-patterns-for-saas/):

- PK: `MARKET#<id>`, SK: `LISTING#<id>`
- GSI: `geoHash` + `status` for bbox pre-filter before OpenSearch
- Stream → OpenSearch indexer (idempotent upsert)

### Search — OpenSearch geo + optional k-NN

- Map `location` as **`geo_point`** for `geo_distance` and polygon filters
- Enable k-NN when marketing needs "homes like this" — watch memory: HNSW footprint scales with vector count ([OpenSearch quantization blog](https://aws.amazon.com/blogs/big-data/cost-optimized-vector-database-introduction-to-amazon-opensearch-service-quantization-techniques/))
- **Amazon Location** Place Index for autocomplete if address parsing is messy — do not geocode twice in app and index

### Images — cost control

- Generate `thumb`, `card`, `gallery` WebP at ingest
- **Intelligent-Tiering** after 90 days for stale listings
- CloudFront cache keys per variant — never serve raw MLS TIFF to mobile

> **What broke** — Spring season week 2. **Search p95** jumped **48 ms → 410 ms** while CPU looked fine. Root cause: **OpenSearch** shard hot-spot on single high-traffic metro + unbounded `geo_polygon` queries from a partner widget. **Detection:** `SearchLatency` + slow query log. **Fix:** route top metros to dedicated index alias + rate limit partner API key. **p95 back under 80 ms within 12 hours**.

## When NOT to escalate

| Situation                 | Stay lighter                            |
| ------------------------- | --------------------------------------- |
| MVP, one MLS, map-only    | API Gateway + DynamoDB GSI              |
| &lt; 50k listings         | Skip k-NN and second index              |
| No OpenSearch ops owner   | Managed cluster minimum + runbook first |
| CRE analytics / portfolio | Data lake post — not consumer search    |

## What to Do This Week

1. Inventory MLS connectors — fill [mls-ingest-cost-worksheet.csv](https://www.factualminds.com/examples/architecture-blog-2026/real-estate-proptech/mls-ingest-cost-worksheet.csv).
2. Run [listing-search-tier-decision-matrix.md](https://www.factualminds.com/examples/architecture-blog-2026/real-estate-proptech/listing-search-tier-decision-matrix.md) with product + finance.
3. Implement DynamoDB canonical + one OpenSearch index for top market only.
4. Switch image bucket to Intelligent-Tiering; measure CloudFront bytes-out for 7 days.
5. Defer Bedrock listing copy until human review workflow exists.

> **Reproduce this** — Download [mls-ingest-cost-worksheet.csv](https://www.factualminds.com/examples/architecture-blog-2026/real-estate-proptech/mls-ingest-cost-worksheet.csv). Set `sync_frequency_per_day` truthfully; flag any feed &gt;4×/day with full image sync for cost review.

## What This Post Doesn't Cover

- **Title / escrow transaction workflows** — downstream of search
- **Commercial CRE lease abstraction** — document AI separate path
- **Mortgage origination** — fintech compliance cluster
- **Specific MLS vendor contracts** — legal/commercial, not architecture

We have not load-tested **k-NN** above **2M** vectors on a single domain — run OpenSearch sizing calculator before national semantic search rollout.

**Related:** [Real estate industry hub](/industries/aws-real-estate/) · [Serverless services](/services/aws-serverless/) · [Data analytics](/services/aws-data-analytics/) · [Cost optimization](/services/aws-cloud-cost-optimization-services/)

## FAQ

### When should we add OpenSearch vs DynamoDB GSI geo alone?
Stay on DynamoDB when you have under ~100k active listings, bbox-only map search, and sustained search QPS under ~50. Add OpenSearch when you need polygon filters, full-text facets, relevance ranking, or embedding similarity (k-NN up to 16,000 dimensions per AWS OpenSearch docs).

### When should we NOT run 12x/day full MLS image re-sync?
Never at scale — full image re-sync on high-frequency feeds dominates Lambda and S3 PUT cost. Use delta sync with ETag/last-modified, resize to WebP variants on first ingest only.

### What breaks when MLS duplicate keys collide?
Buyers see two pins for one property; saved-search emails double. Symptom: OpenSearch doc count exceeds DynamoDB canonical count. Fix: composite key (marketId, listingId) + address-hash dedupe in Step Functions before index.

### How does this differ from retail omnichannel analytics?
Retail lakehouse posts focus on orders, inventory, and CDP events. PropTech focuses on MLS ingest cadence, geo search latency, and image CDN economics — different KPIs and ingest shapes.

### Should we use Rekognition for property condition scoring?
Off-the-shelf labels work for marketing tags (pool, kitchen). Condition scoring (roof, foundation) needs Custom Labels and typically 500+ labeled images per class — do not promise AVM-grade condition from default labels alone.

### What could go wrong during spring-buying-season traffic?
OpenSearch cluster undersized while CloudFront cache hit ratio drops on new listing photos. Mitigate with autoscaling policy on search tier, pre-warm popular markets, and separate image origin from API origin.

---

*Source: https://www.factualminds.com/blog/aws-real-estate-proptech-reference-architecture-2026/*
