Property registration against a government registry, from Salesforce
An Apex and LWC suite automating property registration with Dubai’s land registry — register, upload, submit, cancel, and status check — reached through a MuleSoft proxy layer rather than direct callouts.
- Context
- A leading UAE real estate developer
- Role
- Senior Salesforce Developer
- Period
- 2025 — present
- Systems
- Salesforce ⇄ MuleSoft ⇄ Dubai Land Department (OQOOD)
At a glance
A legally required, externally controlled process now runs inside the system that holds the transaction, with its state kept current automatically rather than chased by a person.
- Automated the Salesforce property-registration workflow with DLD and OQOOD.
- Reduced manual data exchange and manual status follow-up.
- Added validation, error handling, asynchronous processing, and automated reconciliation of registration status.
Jump to
Overview
What this was
Property registration in Dubai runs through the Dubai Land Department and its OQOOD system for off-plan sales. Registration is a legal precondition, not an administrative nicety: until a unit is registered, the sale is not complete. This work moved that process into Salesforce, so the team that owns the transaction can register, submit supporting documents, check status, and cancel without leaving the record they are working on.
Business context
A large UAE real estate developer running property sales on Salesforce. Registration with the Dubai Land Department is mandatory and its interface is defined entirely by the registry — the schema, the validation rules, and the availability window are external constraints, not negotiable design inputs. That makes it a textbook case for keeping the external contract behind a boundary the platform controls.
Delivery timeline
- 01
Contract analysis
Mapped the registry operations and their required payloads.
- 02
Proxy design
Agreed the MuleSoft interface so Apex never faces the registry directly.
- 03
Build
Apex service classes per registry operation, with LWC entry points.
- 04
Document handling
Object-store sync for transaction-linked files.
- 05
Status reconciliation
Status check flow to keep Salesforce aligned with the registry.
Business problem
Property registration is legally required, externally controlled, and was handled outside the system that holds the transaction.
A manual, off-platform step
Registration happened outside Salesforce, so the record holding the transaction did not reflect its registration state.
No visibility of registry status
Establishing where a submission had reached required checking another system, and the answer was not visible to the wider team.
Document handling was detached from the transaction
Supporting documents required by the registry were not systematically linked to the record they belonged to.
A compliance process without an audit trail
A legally significant step carried no systematic record in the platform of what was submitted, when, and by whom.
Challenges
What made this harder than it looks
- 01
The contract belongs to a government system
Payload shape, validation, and error semantics are defined by the registry. The integration has to accommodate them exactly, and adapt when they change, with no influence over either.
- 02
Multiple distinct operations, one coherent process
Register, upload, submit, cancel, and status check are separate operations with different payloads and different failure modes, but a user experiences them as one registration process.
- 03
A failed submission has legal weight
This is not a sync that can quietly retry. A submission that fails partway, or succeeds without Salesforce recording it, creates a compliance discrepancy rather than a data discrepancy.
- 04
Documents are part of the transaction, not attachments to it
The registry requires supporting files. Those files need durable, retrievable storage tied to the transaction record, outside Salesforce file storage limits.
- 05
External availability is outside our control
The registry has its own uptime and response characteristics. Apex transactions cannot be designed on the assumption that it answers promptly.
Architecture
How the system fits together
Salesforce holds the transaction and orchestrates the registration process. MuleSoft sits between Salesforce and the registry as a proxy layer, so the external contract, its authentication, and its instability terminate at the middleware rather than inside Apex.
- Registration LWC to Apex services: initiate
- Apex services to Transaction record: record state
- Apex services to Document storage: documents
- Apex services to MuleSoft proxy: registry operations
- MuleSoft proxy to DLD / OQOOD: registry API
- DLD / OQOOD to MuleSoft proxy: response
- MuleSoft proxy to Apex services: response
- Batch Status Reconciliation to MuleSoft proxy: status request (asynchronous, queued, or scheduled)
- MuleSoft proxy to DLD / OQOOD: status API (asynchronous, queued, or scheduled)
- Batch Status Reconciliation to Transaction record: sync status (asynchronous, queued, or scheduled)
End-to-end flow
- 01
Initiate from the transaction
A user starts registration from the transaction record through a Lightning Web Component, rather than in a separate system.
- 02
Register the unit
An Apex service composes the registration payload and calls the MuleSoft proxy, which forwards it to the registry.
- 03
Upload supporting documents
Required documents are transmitted for the registration, with the files themselves held in external object storage and linked to the transaction.
- 04
Submit for processing
Once registration and documents are in place, the submission is sent to the registry for processing.
- 05
Reconcile registration status
A batch reconciliation process retrieves registration status through MuleSoft and syncs it back onto the Salesforce record. The registry does not call into Salesforce — the platform goes and asks, which is what removes the manual follow-up.
- 06
Cancel where required
A cancellation path handles withdrawn or corrected registrations explicitly, rather than leaving a stale submission in place.
Technologies
Salesforce
- Apex service classes
- Apex callouts
- Lightning Web Components
- Named Credentials
- Custom Metadata
- Transaction data model
Middleware
- MuleSoft
- Object storage
External
- Dubai Land Department
- OQOOD registration system
Solution design
The choices that shaped everything else
One Apex service per registry operation
Register, upload, submit, cancel, and status check are implemented as distinct services rather than one class branching on a mode. Each has its own payload, its own error handling, and its own tests, and a change to one cannot destabilise the others.
MuleSoft as the contract boundary
Apex talks to a stable internal interface; MuleSoft absorbs the registry’s actual schema, authentication, and quirks. When the registry changes, the change is contained in the middleware rather than propagating into platform code.
Registration state lives on the transaction
The transaction record carries where registration has reached, so the process is visible to anyone looking at the deal — not only to the person who submitted it.
Batch reconciliation rather than an inbound callback
Registration status changes on the registry’s timetable, not ours, and an external system cannot be relied on to notify us when it does. A batch reconciliation retrieves status and syncs it onto the transaction — so the platform converges on the registry’s view without anyone chasing it, and without depending on a callback the registry does not offer.
Documents in an object store, references in Salesforce
Supporting files live in external object storage and are referenced from the transaction. Salesforce holds the relationship and the metadata; the object store holds the bytes.
Technical decisions
What was decided, why, and what it cost
Every decision below is paired with its trade-off. A design choice without a stated cost usually means the cost was not examined.
Route through MuleSoft instead of calling the registry from Apex
Rationale
It puts the volatile external contract, credential handling, and transformation in a layer built for it, and keeps a government schema out of platform code. It also gives the integration an observable point outside Salesforce.
Trade-off
Another system in the path — more infrastructure, another hop to debug, and a middleware dependency. Justified by how often an externally owned contract changes.
Separate services per operation rather than one gateway class
Rationale
The operations share a destination but nothing else. Splitting them keeps each payload and failure path independently readable and testable.
Trade-off
More classes and some shared scaffolding. Preferable to one class with a branch per operation.
Store documents outside Salesforce
Rationale
Transaction documents accumulate indefinitely and are large. An object store is the right home; Salesforce keeps the reference and the relationship.
Trade-off
Retrieval crosses a system boundary, and the two stores can diverge if the sync is not monitored.
My responsibilities
What I personally owned
- Built the Apex service layer covering the register, upload, submit, cancel, and status check operations.
- Built the Lightning Web Component interface for initiating and monitoring registration from the transaction record.
- Built the batch reconciliation that syncs registration status from the registry back into Salesforce, removing manual follow-up.
- Designed the integration boundary against the MuleSoft proxy layer.
- Implemented the document handling that links supporting files to the transaction record.
- Handled registry error responses and reflected them in the platform.
Implementation process
How it was actually built
- 01
Mapped the registry operations before writing Apex
Each operation, its required payload, and its failure semantics were established first — with an externally owned contract, guessing is expensive.
- 02
Agreed the proxy interface early
Fixing the Salesforce-to-MuleSoft contract up front let both sides be built against a known shape rather than against each other.
- 03
Built operation by operation
Register first, then documents, then submit, then status and cancel — each usable before the next began, rather than one large simultaneous release.
Security considerations
What was protected, and how
Registry credentials never reach Salesforce
Authentication to the government system is held at the MuleSoft layer. Salesforce authenticates to the proxy through Named Credentials and holds no registry credential.
Personal and transaction data crosses a controlled boundary
Registration payloads carry buyer and property data. That data leaves the platform only through the proxy, over one auditable path, rather than from multiple places in Apex.
Document access is mediated, not public
Blob storage is reached through the platform rather than exposed to end users, so document access follows the same record access as the transaction.
A compliance action leaves an audit trail
What was submitted, when, and its registry outcome is recorded against the transaction, because the process has legal significance.
Business value
A legally required, externally controlled process now runs inside the system that holds the transaction, with its state kept current automatically rather than chased by a person.
- Automated the Salesforce property-registration workflow with DLD and OQOOD.
- Reduced manual data exchange and manual status follow-up.
- Added validation, error handling, asynchronous processing, and automated reconciliation of registration status.
- Improved visibility of external registration status inside Salesforce, on the record the team already works from.
- Isolated the external contract behind middleware, so registry changes do not destabilise platform code.
Lessons learned
What I took from it
A proxy layer earns its keep against an external contract
When the schema belongs to someone else, a boundary that absorbs change is not over-engineering — it is the thing that keeps platform code stable.
Compliance processes need explicit state, not inferred state
A legally significant step should record what actually happened, confirmed against the external system, rather than inferring success from the absence of an error.
Documents belong in a store designed for documents
Treating file storage as a separate concern from the record model avoided a platform storage problem before it became one.
Future improvements
What I would do next
Listing the known gaps is part of the handover. A system described as finished usually means nobody looked hard enough.
Retry and dead-letter handling at the proxy
Queued retry with a dead-letter path for permanently failed submissions would make outages recoverable without manual resubmission.
Improvement 1A registration state dashboard
Registration status across the portfolio, rather than per transaction, would let the business see where submissions are stalled.
Improvement 2
Keep reading