If you've ever worked in property finance — or built tools for developers (the bricks-and-mortar kind) — you'll know that the capital stack is everything. It determines who puts money in, who gets paid first, and what returns each party can expect.
I've spent the past year building internal tooling for JV Equity, a joint venture and equity funding desk for UK property developers. Along the way, I've learned a surprising amount about how financial modelling intersects with software engineering. Here's what I wish someone had told me at the start.
What Is a Capital Stack?
In property development, the capital stack is the layered structure of funding sources used to finance a project. Think of it as a priority queue for money:
- Senior Debt (60-70% LTC) — The bank or specialist lender. First to be repaid, lowest risk, lowest return.
- Mezzanine Finance (10-15% LTC) — Fills the gap between senior debt and equity. Higher risk, higher return.
- Equity (15-30% LTC) — The developer's own capital plus any JV equity partner contributions. Last to be repaid, highest risk, highest potential return.
The percentages shift depending on the project, the market, and the lender's appetite. But the principle is constant: risk and return are inversely correlated with stack position.
Why This Matters for Software
If you're building any kind of property finance platform — whether it's a lending marketplace, a deal-matching tool, or even a simple appraisal calculator — you need to model this stack accurately. Get it wrong and your users will make bad decisions based on your outputs.
Here's a simplified TypeScript model I built for our internal deal appraisal tool:
interface StackLayer {
name: string;
type: 'senior_debt' | 'mezzanine' | 'equity' | 'jv_equity';
amount: number;
rate: number; // annualised
term_months: number;
priority: number; // 1 = highest priority for repayment
}
interface CapitalStack {
gdv: number; // Gross Development Value
total_costs: number;
layers: StackLayer[];
}
function calculateWaterfall(stack: CapitalStack): Map<string, number> {
const profit = stack.gdv - stack.total_costs;
const sorted = [...stack.layers].sort((a, b) => a.priority - b.priority);
let remaining = stack.gdv;
const returns = new Map<string, number>();
for (const layer of sorted) {
const interest = layer.amount * (layer.rate / 12) * layer.term_months;
const totalOwed = layer.amount + interest;
const payout = Math.min(remaining, totalOwed);
returns.set(layer.name, payout - layer.amount); // net return
remaining -= payout;
}
// Remaining profit split according to equity arrangements
if (remaining > 0) {
const equityLayers = sorted.filter(
l => l.type === 'equity' || l.type === 'jv_equity'
);
const totalEquity = equityLayers.reduce((sum, l) => sum + l.amount, 0);
for (const layer of equityLayers) {
const share = (layer.amount / totalEquity) * remaining;
const current = returns.get(layer.name) || 0;
returns.set(layer.name, current + share);
}
}
return returns;
}
This is deliberately simplified. A production model would need to handle arrangement fees, exit fees, rolled-up interest vs. serviced interest, phased drawdowns, and profit-share waterfalls with hurdle rates.
The Equity Gap Problem
Here's where it gets interesting from both a financial and a technical perspective. Most UK property developments stall not because of planning or construction issues, but because of the equity gap.
A typical scenario: a developer secures planning consent for a £5m GDV residential scheme. They approach a lender who offers 65% LTC (£2.6m against £4m total costs). The developer needs to find £1.4m in equity — but they only have £400k of their own capital. That leaves a £1m gap.
This is precisely the problem that JV equity funding solves. A JV equity partner contributes the missing capital in exchange for a share of the development profit. The deal structure might look like this:
GDV: £5,000,000
Total Costs: £4,000,000
Senior Debt: £2,600,000 (65% LTC, 7.5% pa)
Developer Equity: £400,000
JV Equity: £1,000,000
Expected Profit: £1,000,000
Profit Split: 60/40 (developer/JV partner)
Modelling JV Structures in Code
The tricky part of modelling JV equity deals is that profit splits aren't always linear. Many structures use hurdle rates — minimum return thresholds that change the profit-sharing ratio:
interface ProfitShare {
hurdle_irr: number; // IRR threshold
developer_share: number;
jv_share: number;
}
interface JVStructure {
jv_contribution: number;
developer_contribution: number;
preferred_return: number; // e.g. 8% pa to JV partner
profit_tiers: ProfitShare[];
}
function calculateJVReturns(
structure: JVStructure,
totalProfit: number,
term_months: number
): { developer: number; jv_partner: number } {
// First: pay preferred return to JV partner
const prefReturn = structure.jv_contribution
* (structure.preferred_return / 12)
* term_months;
let distributableProfit = totalProfit - prefReturn;
let developerReturn = 0;
let jvReturn = prefReturn;
// Then: split remaining profit according to tiers
for (const tier of structure.profit_tiers) {
const tierProfit = distributableProfit; // simplified
developerReturn += tierProfit * tier.developer_share;
jvReturn += tierProfit * tier.jv_share;
}
return { developer: developerReturn, jv_partner: jvReturn };
}
Lessons Learned
Building financial models in code taught me several things:
Precision matters more than you think. Rounding errors compound across a 24-month development timeline. Use fixed-point arithmetic or a library like big.js for financial calculations. Never use floating point for money.
Edge cases are where deals break. What happens if the project runs over budget? If the GDV comes in 10% below forecast? Your model needs to handle downside scenarios, not just the base case.
Domain expertise is non-negotiable. I spent weeks talking to brokers, lenders, and developers before writing a single line of code. Financial modelling without domain knowledge produces technically correct but commercially meaningless outputs.
Regulatory compliance shapes architecture. FCA regulations around financial promotions and advice mean you need to be careful about what your tool "recommends" vs. what it "illustrates." This affects everything from UI copy to API response structures.
What We're Building Next
The capital stack model was just the foundation. We're now working on deal-matching algorithms that pair developers with appropriate equity partners based on project type, geography, ticket size, and risk profile. If you're interested in PropTech or financial software engineering, the UK property development space is full of problems waiting to be solved.
You can learn more about how JV equity structures work for UK property developers at jvequity.co.uk.
Have you built financial models or PropTech tools? I'd love to hear about your approach to the capital stack problem in the comments.
For further actions, you may consider blocking this person and/or reporting abuse
