Case Study · Client Project
Loans & Real Estate Platform
Two businesses — loan broking and real estate — run as one company, without ever letting their data become one dataset.
Role
Full-stack product design & engineering
Stack
Our client needed to run two businesses — loan broking and real estate — as one company without ever letting them become one dataset. A loan applicant’s income documents and a property buyer’s site-visit history live under different commercial relationships, different staff, and different compliance expectations. Merge them and you create a liability; split them into two systems and you pay twice for every shared concern: identity, payouts, referrals, notifications, reporting. We designed and built the whole platform — public marketing site, six role-based workspaces, the API behind them, and the infrastructure they run on.
2
Businesses, one platform
6
Role-based workspaces
~50
Screens
13
Finance calculators
72
Reviewed migrations
233
API test modules
Segregation enforced by the database
Every business record carries one immutable business line — loans or real estate. The wall doesn’t sit in the UI, where any API call could walk around it — it sits in PostgreSQL. Every request opens a transaction that sets the caller’s identity, role, and business line as session variables, and Row-Level Security policies filter each table against them: Clients see only their own records, staff and Agents stay inside their line, Admins bypass the line filter. Application-layer checks sit on top as defence in depth — but if they were all deleted tomorrow, the database would still refuse to hand a loans telecaller a property record.
This shapes the interface too. Loans surfaces are green, real estate amber, and the two accents never share a screen — so a user always knows which business they’re operating in, and the navigation hides line-specific tools outright rather than greying them out.
One login, six different jobs
Each role shares one database and one sign-in, yet gets an interface built for its actual work.
Admin
Runs the whole business across both lines — pipelines, users, agents, approvals, payouts, CMS, broadcasts, analytics, and a full audit log.
Sub Admin
Delegated administration of the operational surfaces — listing review, document verification, and commission approval.
Agent
Works their leads, submits property listings for review, and tracks earnings — always inside a single business line.
Telecaller
Works an assigned lead queue and logs call outcomes manually against their line.
Employee
Works an assigned task queue with document handling and verification.
Client
Tracks loan applications end to end or works the property side — and, if they hold both, switches between two visually distinct workspaces rather than a blended one.
The whole platform, end to end
Public marketing site
Ten SEO-oriented pages and thirteen finance calculators — EMI, eligibility, prepayment, LAP, home affordability, stamp duty, GST on property, rental yield, balance transfer and more — each a standalone landing page with structured data. Hero banners and content are CMS-driven with scheduled publish windows, served through incremental static regeneration so editors schedule a campaign without a deploy.
Six role-based workspaces
Around fifty screens in total, each built for its role’s actual job: Clients apply, upload, compare offers and book site visits; Agents work leads and listings; Telecallers and Employees work their queues; Admins and Sub Admins run the pipelines, approvals, payouts, CMS and audit log.
Auth for the Indian market
Identity is the mobile number — one number, one account — with a separate display-only public ID so references never leak database keys. One-time passcodes arrive as an automated voice call via 2Factor.in with email fallback, rate-limited in Redis. Sessions are JWTs with per-token IDs that can be revoked centrally.
Payout rails, deliberately scoped
RazorpayX disbursement handles cashback, referral and commission payouts only — never loan principal or property funds, which stay with the lender and the buyer. Payouts pass safety guards before release, and scheduled jobs reconcile them against the provider so a lost API response can never double-pay or strand a beneficiary.
Background work as its own service
A dedicated APScheduler service runs every recurring job — payout reconciliation, paid-payout auditing, scheduled CMS activation, orphaned-upload cleanup, and data-retention purges. Jobs are idempotent and logged, and never run inside the web tier.
How it was built to last
Contract-first
The API’s OpenAPI schema generates the frontend’s TypeScript client. Types are never hand-duplicated across the boundary, and CI fails on drift.
Reviewed migrations
72 Alembic migrations, expand-and-contract, with rollback notes. No silent column or table drops.
Tested
233 API test modules alongside frontend unit tests, run in CI on every change.
Privacy by construction
KYC documents are purged when an application is rejected, uploads are content-type verified, retention purges run on schedule, account deletion is a real path, and mobile numbers are masked in logs.
Designed states, not just happy paths
Every async surface ships loading, empty, error and success states, and every page works from 375px up.
A production-ready platform where the hardest requirement — two businesses that must never bleed into each other — is guaranteed by the database rather than by discipline, and where the six roles that share it each get an interface built for their actual job instead of one dashboard with things hidden.
Have a platform that has to keep two worlds apart?
Tell us about the constraint that keeps you up at night, and we’ll show you how we’d guarantee it in the architecture — not just the UI.