The short answer
Several stacks work for a real estate platform, and the one your team already runs well is a legitimate choice. Three decisions carry most of the weight: where map and filter search runs (in the database or in a separate search engine), how public listing pages are rendered (as HTML on the server), and how many systems your team can operate. Each layer below ends with a “choose this when” table, and the worksheet at the end collects the questions that decide them.
This guide covers the choice of technology only. For budgets see what it costs to build a real estate platform; for how listings get from the MLS into the database see the MLS data pipeline architecture.
What listing data asks of a stack
- Records are wide and sparse. The RESO Data Dictionary 2.0 defines 41 resources, 1,745 fields and 3,683 lookups, and on MLS Grid each record contains only the fields converted from its originating MLS.
- Every listing has a location, and buyers search by map area, radius and drawn shape.
- Your copy is a replica. MLS Grid, for one, does not support real-time access and provides the data through replication, so the search index, the cache and the rendered pages are copies of a copy, and each needs a rule for how stale it may be.
- Each listing carries a set of photos, and on MLS Grid you must maintain your own copy of all media files.
1. System of record: PostgreSQL with PostGIS, MongoDB or MySQL
| Choose | When |
|---|---|
| PostgreSQL with PostGIS | Listings sit among relational data (agents, tenants, saved searches, leads, billing), you want spatial joins such as “listings inside this school boundary”, or search will run in the database at first. |
| MongoDB | The listing document is the center of the product, feeds differ widely in shape, and a separate search engine will handle complex queries anyway. |
| MySQL | The team and application are already on MySQL and geospatial needs are modest. Check the spatial functions you need first. |
One PostGIS detail to settle early: its geography type takes longitude and latitude directly, but fewer functions are defined on it and they take more CPU time; PostGIS suggests it for data that covers a continental region, which a US and Canada platform does. A sound default is a geography point column per listing with a GiST index, which gives radius queries in meters without choosing a projection; reach for geometry only if you need a function that geography lacks. Also check support windows: PostgreSQL supports a major version for 5 years after its initial release.
2. Search: a search engine, the database or a hosted service
Listing search is filters, geography (map bounds, radius, drawn polygon), free text and autocomplete. Each option handles the first two. They differ on the rest and on what you must run.
- Elasticsearch and OpenSearch. Both store points and shapes and query them by bounding box, distance and polygon (Elasticsearch geo queries, OpenSearch geographic queries). Both offer as-you-type suggestions (Elasticsearch completion suggester, four OpenSearch autocomplete methods). Both can group points into map-tile grid cells, which is what clustered map pins need (Elasticsearch geotile grid aggregation, OpenSearch geotile grid aggregation). Elasticsearch documents that a stored document is searchable within 1 second, so the delay a buyer sees is set by your sync, not by the index. For rebuilds, both let you fill a new index and then repoint an alias: Elasticsearch lists reindexing data without downtime as a use of aliases, and OpenSearch states that alias changes are atomic. The licenses differ: OpenSearch is released under the Apache License, Version 2.0, and Elastic offers AGPLv3 alongside SSPL and the Elastic License.
- The database itself. PostgreSQL combines PostGIS filters with built-in text search, where GIN indexes are the preferred text search index type, and the pg_trgm module adds fast searching for similar strings. One system, one copy, no sync job; you write autocomplete and ranking yourself.
- A hosted search service. Algolia filters around a central point and inside rectangular or polygonal areas; Typesense filters records by distance or area and sorts by distance from a point. They meter differently, which matters more than any list price: Algolia's plans count search requests and records, while Typesense Cloud sells a dedicated cluster, with no limits on records or operations, sized by memory. Cost either one at your own record count (answer 1 in the worksheet) and query volume, and remember that a map that re-queries on every pan multiplies requests. Also read your MLS license before sending listing data to any third-party service.
| Choose | When |
|---|---|
| Search in PostgreSQL | A few markets, filters plus map bounds and radius, and a small team. Moving search out later does not change the system of record. |
| Elasticsearch or OpenSearch | Autocomplete across addresses and neighborhoods, clustered map pins, relevance tuning, or a system of record that is slow at ad hoc queries. You accept a second copy of the data and a reindex job. |
| A hosted search service | You want those features without running a cluster, its metering fits your record count and query volume, and your MLS agreements allow the data to be held there. |
Whichever you choose, the index is a derived copy: it must be rebuildable from the system of record at any time, and a record your license no longer lets you display has to leave it as well as the database. The pipeline guide covers which records may enter the index and how deletions reach it.
3. Cache: what to store in Redis and when to drop it
A cache is optional. Add one when the same expensive answers are requested repeatedly: popular search results, autocomplete responses, map cluster counts, per-tenant configuration. Do not cache anything whose staleness would break a display rule, such as a listing's status.
Redis has the tools the job needs. A key can carry a timeout after which it is deleted automatically. A memory limit with an eviction policy caps the memory used for cache data. And UNLINK removes keys without blocking, reclaiming memory in a different thread.
The design question is invalidation, and for listing data the answer is the sync. Either set the timeout to the sync interval, or have the sync job delete the keys for the markets it just changed. Our real estate SaaS case study describes the first approach: Redis as a read-through cache with a 2-hour TTL matched to a 2-hour sync, and property detail pages read straight from the database so that status, price and photo changes are never served from cache.
| Choose | When |
|---|---|
| No cache yet | Search answers fast enough from the index or database, or you cannot yet say what invalidates each key. |
| Timeout equal to the sync interval | Sync runs on a fixed schedule. A cached result can then lag the database by up to one interval, on top of the sync's own lag behind the MLS; both together must fit your license's refresh rule. |
| Deletion by the sync job | Sync is frequent or event-driven and you can key the cache by market or feed. |
4. Backend language and framework
All five options below can replicate an MLS feed, serve an API and run background jobs. In our view, language benchmark rankings are a weak basis for this choice: in a listing platform the waiting is mostly in the database, the search index and the feed's rate limits. We would judge on the ecosystem for this work, whom you can hire, and how long each version is supported:
| Choose | When |
|---|---|
| Node.js with TypeScript | The frontend is React or Next.js and you want one language and shared types across the stack. |
| Python | Valuation models, natural-language search or heavy data work are part of the product, or the team is a Python team. |
| PHP with Laravel | The existing application or team is Laravel and the platform is mostly forms, accounts, CRM screens and jobs. |
| .NET | The company already runs Microsoft infrastructure and employs .NET developers. |
| Go | You have Go engineers and the workload is ingestion services and APIs more than screens. |
Two languages in one platform is common and reasonable: the W3|re case study lists both Node.js and Python in its stack, next to a valuation model and natural-language search. On hiring, look at the candidates and agencies available to you at your budget; a global popularity survey says little about that.
5. Frontend rendering: listing pages must arrive as HTML
Listing, neighborhood and search landing pages exist to be found. Google processes JavaScript pages in three phases: crawling, rendering and indexing, and a page waiting to be rendered may stay on the queue for a few seconds, but it can take longer. Google's own advice is that server-side or pre-rendering is still a great idea because it makes your website faster for users and crawlers, and not all bots can run JavaScript. It calls serving bots a separate pre-rendered version a workaround and not a long-term solution.
So pages that must rank are rendered on the server or generated ahead of time, and screens behind a login can be client-rendered. Next.js defines a strict single-page app as served by one HTML file, with every route and data fetch handled by JavaScript in the browser. The alternatives for public pages:
- Static generation. generateStaticParams statically generates routes at build time. We would use it for a small set of pages that change rarely. Building every listing of a full MLS at each deploy is the case ISR exists for.
- Incremental static regeneration. ISR lets you update static content without rebuilding the entire site and handle large amounts of content pages without long build times. Pages can be refreshed on a timer or on demand, for example with revalidateTag, which invalidates cached data for a specific tag, called by the sync job. ISR needs the Node.js runtime and is not supported in a static export.
- Server rendering on each request. Right for search result pages with many filter combinations and for anything personalized.
| Choose | When |
|---|---|
| ISR or server rendering | Public listing detail, city, neighborhood and saved-search landing pages: anything that should appear in search results. |
| Static generation | Marketing pages, guides and a small, slow-changing inventory. |
| Client-only SPA | Agent dashboards, CRM screens, admin tools and investor portals behind a login, where indexing is not wanted. |
Next.js is one way to get all three in one codebase; any server-side framework that returns complete HTML meets the requirement. A Next.js major version stays in Maintenance LTS for two years following its initial release, so budget for framework upgrades.
6. Media storage and delivery
Where the feed requires you to hold your own copies of listing photos, as MLS Grid does, the usual design is object storage for the originals, a CDN in front, and resized variants made on upload or on first request. Amazon S3, as one example, is designed to provide 99.999999999% durability, and a CDN such as CloudFront delivers content through a worldwide network of edge locations. If the frontend is Next.js, its image optimization works self-hosted with zero configuration under next start, but images are optimized at runtime, not during the build, so at MLS photo volumes that work competes with page rendering unless you move it to a separate service.
| Choose | When |
|---|---|
| Resize on first request, cache at the CDN | A large inventory in which most photos are rarely viewed; you resize only what is looked at. |
| Resize on ingestion | A smaller inventory, a fixed set of sizes, and a media worker that already touches each photo. |
| A separate image service | Photo traffic is heavy enough to slow the application servers. |
7. Hosting
Hosting follows from the layers above and from who will be on call. Next.js can be deployed as a Node.js server, a Docker container, a static export, or adapted to run on different platforms; if you run several instances yourself, note that each Kubernetes pod keeps its own copy of the cache unless you configure a shared one. Managed databases remove backups and patching from your list; Amazon RDS for PostgreSQL, for one, supports the PostGIS extension; confirm the extensions you need before you sign up.
| Choose | When |
|---|---|
| A platform plus managed database and search | A small team without operations staff, and no component that needs a long-running process the platform does not offer. Check where sync and media workers would run before you commit. |
| Containers on a cloud with managed data services | Several services (API, sync and media workers) and someone who owns deployment. |
| Your own virtual servers | Cost control matters most and you have the skills to patch, back up and monitor. |
Two published stacks, as worked examples
These are what two of our case-study pages state, not a house standard.
- White-label agent websites for a brokerage. Next.js with ISR, Node.js, MongoDB, Elasticsearch, Redis, AWS (S3 and SES) and Linode / VPS hosting. The page gives the reason for the split: property search queried MongoDB directly and took 3 to 5 seconds under load, so MongoDB stayed the source of truth, Elasticsearch took over search, filters, geo-queries and auto-suggestions, and Redis cached repeated queries.
- W3|re, a multi-market brokerage platform. Next.js, React Native, Node.js, Python, PostgreSQL, Redis, Apache Kafka, Mapbox GL and AWS EKS, among others, with a pipeline that ingests from four MLS systems and deduplicates cross-listed properties.
One uses a document database and the other a relational one. Both fit what their pages describe.
The stack worksheet
Answer these on one page before anyone proposes a technology.
| Question | Your answer | What it decides |
|---|---|---|
| 1. Listing volume | Active listings, plus sold history you will keep | Whether database search is enough; hosted-search pricing; static build feasibility |
| 2. MLS feeds | How many, on which platforms, with how many local fields | How much per-MLS data needs a flexible column or document; number of sync workers |
| 3. Search features | Filters, map bounds, radius, drawn polygon, autocomplete, clustered pins, natural language | Database search, a search engine, or a hosted service |
| 4. Data around listings | Tenants, agents, leads, saved searches, billing, documents | Relational or document system of record |
| 5. Pages that must rank | Which page types, how many, how often they change | ISR, server rendering or static; revalidation hooked to sync |
| 6. Freshness | Sync interval and the refresh rule in each license | Cache timeouts, page revalidation, index refresh |
| 7. Team skills | Languages and databases the team runs in production today; who you can hire | Backend language, and often the database |
| 8. Compliance | MLS license terms on third-party processors and AI use; privacy law where your users are | Hosted versus self-run services; hosting region |
| 9. Operations budget | Who is on call, and monthly spend you accept for managed services | Number of separate systems; platform versus cloud versus servers |
| 10. Media | Photos per listing, sizes needed, retention after a listing closes | Storage size, resize strategy, CDN |
If answers 1 to 3 are small (one or two feeds, filters and a map), one database, one application and server-rendered pages are enough. Add a search engine, a cache and separate workers when an answer calls for them. Feed and license fees are a separate line: the MLS and IDX cost calculator adds up published fees for the boards you pick.
Frequently Asked Questions
Is PostgreSQL or MongoDB the right database for a real estate platform?
Both work. PostgreSQL with PostGIS suits platforms where listings sit among relational data, with radius queries in meters on the geography type. MongoDB suits products built around the listing document and supports $geoWithin and $near queries on GeoJSON. Team experience is a fair tiebreaker.
Do I need Elasticsearch for property search?
Not always. PostgreSQL with PostGIS handles filters, map bounds and radius, and has built-in full text search. A search engine earns its place when you need autocomplete, clustered map pins or relevance tuning; Elasticsearch, for example, provides a completion suggester for search-as-you-type.
Can a real estate site be a client-only single-page app?
The logged-in parts can. Public listing pages should arrive as HTML: Google says server-side or pre-rendering is still a great idea because it makes your website faster for users and crawlers, and not all bots can run JavaScript.
Capabilities, pricing models and support windows were read from each technology's own documentation on October 12, 2026, and change with new versions. MySQL's support-lifecycle page could not be read that day, so no MySQL support window is given. No benchmark or popularity survey is cited.
Choosing or reviewing a stack for a listing platform? See our SaaS development service. Every project starts with a 30-minute technical discovery call with an engineer.

