Multi-tenant real estate leasing and billing
A modular-monolith platform covering property master, parties, lease approval workflows, rent escalation, renewals, GST/TDS billing, payments and ledger, with tenant isolation and audit trails.
The challenge
Property owners and public estate bodies run leases, rent escalations, renewals and invoicing across spreadsheets and disconnected tools. Approvals are hard to evidence, and money calculations drift without strict rules. Sensitive party identity data also needs protection at rest and tenant-level isolation.
What we built
The platform is a NestJS and PostgreSQL modular monolith split into bounded contexts (property, party, leasing, rent escalation, renewals, billing, payments, ledger, land and estate, investor, documents, reporting). Leases move through a multi-state approval workflow and occupy the property on activation. Escalation and renewal engines revise rent and raise invoices automatically. Billing computes GST and TDS in integer minor units with golden-file tests. Access combines RBAC and ABAC (CASL) with row-level security SQL, masked KYC fields, an outbox with a pg-boss worker, and a Next.js front end.
Key capabilities
- Property hierarchy with an 8-state lifecycle machine
- Lease approval workflow with occupancy on activation
- Compounding rent-escalation schedule engine producing escalated invoices
- Multi-level renewal workflow that extends term and revises rent
- GST and TDS billing in integer minor units feeding payments and a ledger
- Masked KYC identifiers and encrypted PII at rest
What it delivers
- Lease, renewal and escalation rules are encoded as explicit state machines rather than manual tracking
- Billing arithmetic is deterministic, using integer money and tested against golden cases
- Tenant isolation and role/attribute-based access are enforced in the data and API layers
- Domain events flow through a transactional outbox, so downstream modules react consistently
Have a similar backlog?
Most of our work started as a single painful workflow. Tell us yours.


