Methodology & Data Sources
How we collect, clean, secure, and query Dubai real-estate data for the IRETP demo.
Data Sources
Official Dubai Land Department transaction feed (sales, mortgages, grants, lease-to-own). We loaded a 100,000-row stratified sample for the demo - enough to cover every transaction type, area, and year while keeping query latency under ~1s on the demo Postgres tier and AI Gateway token costs predictable. The same pipeline scales to the full 1.5M+ rows; it's a config flag, not a code change.
View sourceHistorical DLD dataset spanning 1969–2023. Loaded into kaggle_dld_transactions_historic (250K-row sample), kaggle_dld_valuations (73K rows, full), and kaggle_dld_rents (100K-row Ejari sample).
View sourceMulti-year bilingual (Arabic + English) DLD transactions dump. Loaded in full into kaggle_dre_transactions via Kaggle API + psql COPY.
View sourceUAE rental listings scrape (Bayut/Dubizzle-style). Loaded in full into kaggle_uae_rental_listings - powers rental-yield and price-vs-rent queries alongside the transaction data.
View sourcePublic league table of 97 Dubai developers with A+ to D grades derived from DLD completion rate, average delivery delay, escrow flags and litigation history. Scraped with Firecrawl on demand, reconciled against DLD project/transaction counts, then re-scored locally using the six-factor RFP weighting (on-time delivery 25% · RERA compliance 20% · units delivered 15% · completed projects 15% · complaint index 15% · ESG 10%). Powers the Developer Scorecard page.
View sourceIngestion Pipeline
Download
Dubai Pulse Parquet is fetched directly from Hugging Face. Kaggle sources are listed and await credential-based download.
Sample & Filter
DuckDB is used to read Parquet/CSV, apply stratified sampling (100k rows), and filter out malformed or incomplete records.
Normalize
Columns are renamed to a consistent schema: price fields in AED, areas in sqft, dates as ISO 8601, and categorical fields lower-cased and trimmed.
Load to Postgres
Cleaned data is written to Postgres via bulk COPY. Indexes are built on date, area, property type, and procedure for fast query performance.
Database Schema
Eight tables across four data sources. The AI chat tool can query any of them; individual pages mostly stick to dld_transactions, kaggle_dre_transactions, kaggle_dld_rents, and kaggle_uae_rental_listings.
dld_transactions~100,000 rowsStratified sample of the Dubai Pulse DLD feed - sales, mortgages, grants, lease-to-own. The cleanest recent feed; used by Projects, Speculation, Seasonality.
| Column | Type | Description |
|---|---|---|
| id | BIGSERIAL | Unique row identifier |
| procedure_name | TEXT | Transaction type (Sell, Mortgage, Grant, Lease to Own…) |
| transaction_date | DATE | Date the transaction was recorded |
| property_type | TEXT | Villa, Unit, Building, Land… |
| property_sub_type | TEXT | Flat, Townhouse, Office, Hotel Apartment… |
| property_usage | TEXT | Residential, Commercial, etc. |
| area_name | TEXT | DLD community / district |
| building_name | TEXT | Named building or tower |
| master_project | TEXT | Larger development project name |
| nearest_landmark | TEXT | Nearby landmark |
| nearest_metro | TEXT | Closest Dubai Metro station |
| nearest_mall | TEXT | Closest major shopping mall |
| bedrooms | TEXT | Studio, 1 B/R, 2 B/R… |
| parkings | INTEGER | Number of parking spaces |
| built_up_area_sqft | NUMERIC | Property size in square feet |
| selling_price_aed | NUMERIC | Total transaction value in AED |
| sale_price_per_sqft | NUMERIC | Derived AED per sqft for sales |
| rent_value_aed | NUMERIC | Rent value (only set for rental procedures) |
| rent_price_per_sqft | NUMERIC | Derived AED per sqft for rentals |
kaggle_dre_transactions~1,047,965 rows (full)Full bilingual (Arabic + English) DLD transactions dump from Kaggle (alexefimik). The widest single transaction table.
| Column | Type | Description |
|---|---|---|
| instance_date | TEXT | Transaction date (mixed DD-MM-YYYY / D/M/YYYY) |
| procedure_name_en | TEXT | Transaction type in English |
| property_type_en | TEXT | Villa, Unit, Land, Building |
| property_sub_type_en | TEXT | Flat, Townhouse, Hotel Apartment… |
| property_usage_en | TEXT | Residential, Commercial, etc. |
| area_name_en | TEXT | DLD community / district |
| building_name_en | TEXT | Named building or tower |
| master_project_en | TEXT | Master development name |
| rooms_en | TEXT | Bedroom string (Studio, 1 B/R…) |
| procedure_area | TEXT | Registered area (sqm) |
| actual_worth | TEXT | Transaction value in AED |
| meter_sale_price | TEXT | AED per sqm for sales |
| rent_value | TEXT | Rental value where applicable |
| meter_rent_price | TEXT | AED per sqm for rentals |
kaggle_dld_transactions_historic~250,000-row sampleLong-range historical DLD transactions (Kaggle - zainabhejairi). Use for pre-2010 / multi-decade trend questions.
| Column | Type | Description |
|---|---|---|
| instance_date | TEXT | Transaction date (mixed formats) |
| procedure_name_en | TEXT | Transaction type |
| property_type_en | TEXT | High-level category |
| property_sub_type_en | TEXT | Sub-category |
| area_name_en | TEXT | Community / district |
| master_project_en | TEXT | Master development name |
| rooms_en | TEXT | Bedroom string |
| procedure_area | TEXT | Registered area (sqm) |
| actual_worth | TEXT | Transaction value in AED |
| meter_sale_price | TEXT | AED per sqm |
kaggle_dld_valuations~73,677 rows (full)DLD-registered bank/regulatory valuations. Powers the Valuation gap detector (valuation vs realised sale price).
| Column | Type | Description |
|---|---|---|
| procedure_year | TEXT | Year of valuation |
| instance_date | TEXT | Valuation date |
| property_type_en | TEXT | Villa, Unit, Land… |
| area_name_en | TEXT | Community / district |
| actual_worth | TEXT | Valuation amount in AED |
| actual_area | TEXT | Property area (sqm) |
| property_total_value | TEXT | Total assessed value in AED |
kaggle_dld_rents~100,000-row sample (of 6.5M Ejari)Ejari rental contracts - new vs renewal pricing. Heavily 2018-2019 weighted (see Rents page disclaimer).
| Column | Type | Description |
|---|---|---|
| contract_start_date | TEXT | Lease start |
| contract_end_date | TEXT | Lease end |
| contract_amount | TEXT | Total contract value in AED |
| annual_amount | TEXT | Annualised rent in AED |
| contract_reg_type_en | TEXT | New vs Renew |
| area_name_en | TEXT | Community / district |
| ejari_property_type_en | TEXT | Unit, Villa… |
| ejari_property_sub_type_en | TEXT | Bedrooms encoded here (Studio, 1bed room+Hall…) |
| property_usage_en | TEXT | Residential / Commercial |
| tenant_type_en | TEXT | Person / Company |
| actual_area | TEXT | Leased area (sqm) |
kaggle_uae_rental_listings~73,742 listings (full)Bayut/Dubizzle-style asking-rent scrape across UAE. Powers the rental Map and Metro premium pages.
| Column | Type | Description |
|---|---|---|
| address | TEXT | Listing address |
| rent | TEXT | Asking rent in AED |
| rent_per_sqft | TEXT | AED per sqft |
| beds | TEXT | Bedrooms |
| baths | TEXT | Bathrooms |
| type | TEXT | Apartment, Villa, Townhouse… |
| area_in_sqft | TEXT | Listed area in sqft |
| frequency | TEXT | Yearly / Monthly |
| furnishing | TEXT | Furnished / Unfurnished |
| purpose | TEXT | For rent / For sale |
| city | TEXT | Dubai, Abu Dhabi, Sharjah, Ajman |
| location | TEXT | Neighbourhood |
| latitude | TEXT | Geocoded latitude |
| longitude | TEXT | Geocoded longitude |
| posted_date | TEXT | Date listing was posted |
dre_project_sales_summaryAggregated rollupPre-aggregated project-level sales (count, total volume, avg AED/sqft). Backs the Projects page for fast loads.
| Column | Type | Description |
|---|---|---|
| master_project | TEXT | Project name |
| area_name | TEXT | Community / district |
| year | INTEGER | Year bucket |
| reg_type | TEXT | Off-plan vs Ready |
| transactions | INTEGER | Count of sales |
| total_volume_aed | NUMERIC | Sum of transaction values |
| avg_price_aed | NUMERIC | Average sale price |
| avg_price_per_sqft | NUMERIC | Average AED per sqft |
developers~12 seeded, extensible to 97Developer scorecard — six-factor RFP rating (on-time delivery, RERA compliance, units delivered, completed projects, complaint index, ESG). Powers the Developers page.
| Column | Type | Description |
|---|---|---|
| slug | TEXT | Stable developer identifier |
| name | TEXT | Developer display name |
| founded | INTEGER | Year the developer was founded |
| tier | TEXT | Letter grade (A+ … D) |
| rank | INTEGER | Position in the league table |
| overall_score | NUMERIC | Weighted composite score 0–100 |
| score_on_time_delivery | NUMERIC | On-time handover rate score (weight 25%) |
| score_rera_compliance | NUMERIC | RERA audit / escrow discipline score (weight 20%) |
| score_units_delivered | NUMERIC | Volume-normalised units delivered score (weight 15%) |
| score_completed_projects | NUMERIC | Lifetime completed projects score (weight 15%) |
| score_complaint_index | NUMERIC | Inverse of complaints per 1,000 units (weight 15%) |
| score_esg | NUMERIC | LEED / Estidama certification coverage score (weight 10%) |
| projects_delivered | INTEGER | Handover-signed projects |
| projects_announced | INTEGER | Total announced projects |
| units_delivered | INTEGER | Total handed-over units |
| avg_delay_days | INTEGER | Mean delivery delay vs promised handover |
| escrow_flags | INTEGER | RERA escrow-account flags |
| complaints_per_1000 | NUMERIC | RERA-logged complaints per 1,000 units |
| esg_certified_pct | NUMERIC | % of portfolio with LEED / Estidama |
| rera_rating | TEXT | RERA compliance grade (A+ … C) |
| source_url | TEXT | WealthIQ source page |
| scraped_at | TIMESTAMPTZ | Last Firecrawl refresh |
datasetsMetadataRegistry of ingested datasets - source URL, row counts, last refresh. Used by the ingestion pipeline, not user-facing.
| Column | Type | Description |
|---|---|---|
| slug | TEXT | Stable dataset identifier |
| title | TEXT | Display name |
| source_url | TEXT | Origin (Kaggle / HF / etc.) |
| row_count | BIGINT | Loaded row count |
| last_loaded_at | TIMESTAMPTZ | Most recent refresh |
Security & AI Query Model
Read-Only SQL Guard
The AI does not write to the database. All queries pass through a run_sql PostgreSQL function with three layers of protection:
- Regex gate - queries must start with
SELECTorWITH. - Keyword blacklist -
INSERT,UPDATE,DELETE,DROP,ALTER, and similar are blocked. - Row cap - results are aggregated through
jsonb_aggwhich caps output at 500 rows per query.
AI-to-SQL Flow
When you ask a question in natural language, the following happens:
- The AI receives the database schema and your question.
- It drafts a PostgreSQL SELECT query tailored to the schema.
- The query is executed via the read-only
run_sqlfunction. - If the result is numeric or time-series, the AI emits a
chartJSON block and the UI renders a Recharts visualization inline. - Otherwise, the raw rows are shown in a sortable data table.
Tools & Menu Items
Each page in the VALUS demo is a focused analytical module. Below is what every tool does, how it works, and when to use it.
Chat
/Natural-language Q&A over the full DLD dataset. Ask anything in plain English (or Arabic) and get back a SQL-backed answer, chart, or data table.
How it works: Your question is sent to an LLM together with the database schema. The model drafts a read-only PostgreSQL SELECT query, which is validated and executed against the live dataset. Numeric or time-series results are rendered as Recharts visualisations; tabular results appear in a sortable grid.
Map
/mapInteractive rental-listing heatmap covering Dubai, Abu Dhabi, Sharjah and Ajman. Every dot is a real listing coloured by annual rent.
How it works: 73,000+ scraped listings are geocoded and plotted on a Leaflet map. Filters (city, bedrooms, property type, max rent, posting year) are applied server-side so the browser only renders the matching subset. Click any dot for full listing details.
Projects
/projectsDubai's most-traded residential projects ranked by transactions, total volume, average price and AED/sqft. Filter by area, year range, and registration type (off-plan vs ready).
How it works: Aggregates 1M+ DLD sales transactions at the project level. A top-project card highlights the #1 most-traded tower. The table supports sorting by volume, price, or transaction count, with inline bar visualisations for quick comparison.
Metro
/metroRental premium calculator for every Dubai Metro station. See how much extra tenants pay to live within walking distance of each Red and Green line stop.
How it works: Rental listings are grouped by proximity to each metro station (radius configurable from 800m to 4km). The station average AED/sqft is compared against the citywide average from 34,000+ listings. Stations are ranked by premium percentage.
Speculation
/speculationOff-plan vs ready market gauge. Track the speculative cycle by measuring off-plan transaction share, volume, and price premium over time.
How it works: Splits DLD project-level sales into off-plan (developer primary sales) and ready (secondary resale). Calculates share by transaction count and by volume, plus average AED/sqft for each category. Hot areas (highest off-plan share) and cool areas (ready-heavy) are ranked.
Valuation
/valuationValuation gap detector — compare DLD-registered bank valuations against realised sale prices to detect bubbles and financing discounts.
How it works: For each area, computes the median bank valuation AED/sqft and the median realised sale AED/sqft. The gap percentage = (sale − valuation) / valuation. Positive gaps signal market prices running above bank appraisals; negative gaps suggest financing-side conservatism.
Rents
/rentsNew vs renewal rent comparison. Measures how much newly signed Ejari contracts diverge from renewals — a proxy for tenant repricing risk and landlord pricing power.
How it works: Ejari rental records are classified as new (first-time registration) or renewal (re-registered lease). Median AED/sqft is computed for each group by area and year. A large new > renew gap means sitting tenants are under-market and face sharp increases on renewal.
Seasonality
/seasonalityYear-by-month transaction heatmap for sales and Ejari rentals. Spot quiet months, peak seasons, and long-term shifting patterns.
How it works: Transactions are binned by year and month, then normalised into a heatmap. Click any cell to drill into month-level details: transaction count, median/mean/total value, top areas, top property types, and top projects for that month.
Developers
/developersDeveloper reliability scorecard — one A+ to D grade per Dubai developer, computed from six weighted criteria straight out of the IRETP RFP.
How it works: WealthIQ's public league table is scraped via Firecrawl and reconciled against DLD project and transaction counts. Each developer is re-scored locally with the six-factor RFP weighting: on-time delivery 25%, RERA compliance 20%, units delivered 15%, completed projects 15%, complaint index 15%, and ESG certification coverage 10%. Results are cached in the developers table and refreshed on demand from the page.
Use Cases Covered
- Market Transparency Q&A - average price per sqft by community, top 10 areas by volume, year-over-year trends.
- Investor Insights - median sale prices, rental yield proxies, hotspot detection by transaction volume.
- Regulator Signals - outlier price spikes, unusual transfer patterns, area-level activity dashboards.
- Developer & Project Intelligence - grade every Dubai developer A+ to D on the six-factor RFP scorecard (on-time delivery, RERA compliance, units delivered, completed projects, complaints, ESG), identify the most-traded projects, and benchmark pricing by tower.
- Rental Market Analysis - compare new vs renewal rents, detect tenant repricing risk, and map rental premiums around metro stations.
- Speculation & Market Timing - track off-plan share cycles, spot overheated areas, and time entry/exit using seasonality patterns.