Rent Control and Housing Policy
The appeal and the problem
Rent control caps how much landlords can charge or how fast rents can rise. Its goal is clear: protect tenants from sharp rent increases and let them stay in their homes. The problem is that a price cap changes what landlords do. Over time, some units leave the rental market, and fewer new ones get built.
A price ceiling
In the simplest model, the rental market has a demand curve and a supply curve. The market rent is where they cross. A rent ceiling below the market rent does three things:
- Tenants who keep a unit gain. They pay the gap between the market rent and the ceiling less each month.
- Fewer units are offered. At the lower rent, landlords supply fewer units than before.
- A shortage appears. At the low rent, more people want units than are available.
Some trades that would help both sides no longer happen. That lost value is the deadweight loss.
Time matters
In the short run, the housing stock is fixed. Supply is steep, so a ceiling mostly moves money from landlords to tenants. In the long run, landlords can convert units to condos, sell to owner-occupiers, or skip maintenance. Supply becomes flatter, and the losses grow.
Diamond, McQuade and Qian (2019) found exactly this in San Francisco. Tenants covered by the 1994 expansion of rent control were more likely to stay at their address. But landlords of covered buildings cut the supply of rental housing by 15 percent, often by converting to condos. That pushed up rents for everyone else.
Other tools
Economists often prefer other ways to help renters:
- Housing vouchers pay part of the rent for low-income households. They help without cutting supply, though they can push up rents if supply is fixed.
- More supply, through zoning reform, lowers rents for everyone. See Zoning & Housing Supply.
- Targeted protections, like limits on very large one-year increases, aim at the main fear behind rent control with less effect on supply.
#| standalone: true
#| viewerHeight: 640
library(shiny)
ui <- fluidPage(
tags$head(tags$style(HTML("
.info-box {
background: #eaf2f8; border-radius: 6px; padding: 14px;
margin-top: 12px; font-size: 13px; line-height: 1.8;
}
.info-box b { color: #2c3e50; }
"))),
sidebarLayout(
sidebarPanel(
width = 3,
sliderInput("ceiling", "Rent ceiling (% of market rent):",
min = 50, max = 100, value = 80, step = 5),
sliderInput("elast", "Supply elasticity (low = short run, high = long run):",
min = 0.1, max = 3, value = 0.5, step = 0.1),
uiOutput("info")
),
mainPanel(
width = 9,
fluidRow(
column(7, plotOutput("market_plot", height = "480px")),
column(5, plotOutput("bar_plot", height = "480px"))
)
)
)
)
server <- function(input, output, session) {
Rm <- 2000 # market rent, $ per month
Qm <- 100 # thousand units at the market rent
ed <- 0.5 # demand elasticity at the market point
model <- reactive({
es <- input$elast
# linear curves through (Qm, Rm) with the chosen elasticities
bd <- ed * Qm / Rm; ad <- Qm + bd * Rm # Qd = ad - bd R
bs <- es * Qm / Rm; as <- Qm - bs * Rm # Qs = as + bs R
Rc <- Rm * input$ceiling / 100
Qs <- max(as + bs * Rc, 0)
Qd <- ad - bd * Rc
inv_d <- function(Q) (ad - Q) / bd # willingness to pay
inv_s <- function(Q) (Q - as) / bs # marginal cost of supply
# surplus changes, $ thousands per month (units in thousands)
dwl <- if (Qs < Qm) integrate(function(Q) inv_d(Q) - pmax(inv_s(Q), 0), Qs, Qm)$value else 0
tenant_transfer <- (Rm - Rc) * Qs
tenant_lost <- if (Qs < Qm) integrate(function(Q) inv_d(Q) - Rm, Qs, Qm)$value else 0
landlord_loss <- tenant_transfer + if (Qs < Qm) integrate(function(Q) Rm - pmax(inv_s(Q), 0), Qs, Qm)$value else 0
list(es = es, ad = ad, bd = bd, as = as, bs = bs, Rc = Rc, Qs = Qs, Qd = Qd,
inv_d = inv_d, inv_s = inv_s, dwl = dwl,
tenant_net = tenant_transfer - tenant_lost, landlord_loss = landlord_loss)
})
output$market_plot <- renderPlot({
m <- model()
Q <- seq(0, 180, length.out = 300)
par(mar = c(4.5, 4.5, 3, 1))
plot(Q, m$inv_d(Q), type = "l", lwd = 3, col = "#2c3e50",
ylim = c(0, 4000), xlim = c(0, 180),
xlab = "Rental units (thousands)", ylab = "Monthly rent ($)",
main = "The rental market with a ceiling")
qs_line <- Q[Q >= max(m$as, 0)]
lines(qs_line, m$inv_s(qs_line), lwd = 3, col = "#3498db")
# deadweight loss triangle
if (m$Qs < Qm) {
qq <- seq(m$Qs, Qm, length.out = 60)
polygon(c(qq, rev(qq)), c(m$inv_d(qq), rev(pmax(m$inv_s(qq), 0))),
col = adjustcolor("#e74c3c", 0.3), border = NA)
}
abline(h = m$Rc, lwd = 2, lty = 2, col = "#e67e22")
abline(h = Rm, lwd = 1, lty = 3, col = "#7f8c8d")
# shortage bracket
if (m$Qd > m$Qs) {
arrows(m$Qs, m$Rc - 150, m$Qd, m$Rc - 150, code = 3, length = 0.08, col = "#e67e22", lwd = 2)
text((m$Qs + m$Qd) / 2, m$Rc - 300, "Shortage", col = "#e67e22", cex = 0.9)
}
legend("topright", bty = "n", cex = 0.85,
legend = c("Demand", "Supply", "Rent ceiling", "Market rent", "Deadweight loss"),
col = c("#2c3e50", "#3498db", "#e67e22", "#7f8c8d", adjustcolor("#e74c3c", 0.5)),
lwd = c(3, 3, 2, 1, 10), lty = c(1, 1, 2, 3, 1))
})
output$bar_plot <- renderPlot({
m <- model()
vals <- c(m$tenant_net, -m$landlord_loss, -m$dwl) / 1000
par(mar = c(6, 4.5, 3, 1))
b <- barplot(vals, names.arg = c("Tenants\n(net)", "Landlords", "Lost value\n(DWL)"),
col = c("#27ae60", "#e74c3c", "#7f8c8d"),
ylab = "$ millions per month", main = "Who gains and who loses",
ylim = c(-1, 1) * max(10, 1.2 * max(abs(vals))))
abline(h = 0)
off <- 0.06 * max(10, max(abs(vals)))
text(b, vals + ifelse(vals >= 0, off, -off), sprintf("%.1f", vals), cex = 0.9)
})
output$info <- renderUI({
m <- model()
tags$div(class = "info-box",
HTML(paste0(
"<b>Controlled rent:</b> $", format(round(m$Rc), big.mark = ","), "<br>",
"<b>Units supplied:</b> ", round(m$Qs, 1), "k (was ", Qm, "k)<br>",
"<b>Units wanted:</b> ", round(m$Qd, 1), "k<br>",
"<b>Shortage:</b> ", round(max(m$Qd - m$Qs, 0), 1), "k units<br>",
"<b>Deadweight loss:</b> $", sprintf("%.1f", m$dwl / 1000), "M per month"
))
)
})
}
shinyApp(ui, server)
Things to try
- Short run: set supply elasticity to 0.1. Supply barely falls. The ceiling mostly moves money from landlords to tenants, and the lost value is small.
- Long run: raise supply elasticity to 2 or more. Now many units leave the market, the shortage grows, and the lost value is large.
- Tighten the ceiling: move it from 90% to 60% of market rent. The lost value grows faster than the cut in rent. Deadweight loss grows with the square of the gap.
- Watch the tenant bar: tenants who keep a unit gain, but tenants who cannot find one lose. With flexible supply, tenants as a group can end up worse off.
What the simple model leaves out
Real rent control is messier than the model. It usually exempts new buildings, so it may not stop new construction. It also keeps tenants in units that no longer fit them, because moving means losing the low rent.
Who pays matters too. Ahern and Giacoletti (2022) found that after St. Paul, Minnesota, passed rent control in 2021, property values fell, and some of the gains went to tenants who were not poor.
Connections
- Zoning & Housing Supply: rent control and zoning both act on the supply side, in opposite directions.
- Gentrification & Displacement: rent control is often proposed as a defense against displacement.
- Spatial Equilibrium: when one city caps rents, people and builders respond across cities.
Did you know?
- New York City has had some form of rent regulation since World War II, when federal wartime controls began.
- In 1994, Massachusetts voters ended rent control statewide by a narrow margin. Autor, Palmer and Pathak (2014) used this to study Cambridge, where controlled and uncontrolled buildings sat side by side. Values of never-controlled homes near controlled ones rose after decontrol.
- Rent control is one of the few policies where economists across the political spectrum largely agree. Most argue it reduces the supply and quality of rental housing over time.
Key papers
- Autor, D. H., Palmer, C. J. and Pathak, P. A. (2014). Housing Market Spillovers: Evidence from the End of Rent Control in Cambridge, Massachusetts. Journal of Political Economy 122(3). Controlled units lowered nearby property values.
- Diamond, R., McQuade, T. and Qian, F. (2019). The Effects of Rent Control Expansion on Tenants, Landlords, and Inequality: Evidence from San Francisco. American Economic Review 109(9). Tenants stayed; landlords cut rental supply.
- Ahern, K. R. and Giacoletti, M. (2022). Robbing Peter to Pay Paul? The Redistribution of Wealth Caused by Rent Control. NBER Working Paper 30083. Who paid for rent control in St. Paul.