Why Cities Exist
The basic tradeoff
Cities are expensive. Land costs more, commutes are longer, and the air is dirtier. Yet most people live in them. They come because being close to other people and firms makes them more productive. A city exists when these gains are larger than the costs of crowding.
Gains from size
Bigger cities offer more. Workers find better job matches. Firms find specialized suppliers. Ideas spread faster. Economists call these gains agglomeration economies. A simple way to write them is that output per worker rises with city size \(N\):
\[\text{Gain}(N) = A \cdot N^{\gamma}\]
where \(\gamma\) is the agglomeration elasticity. Rosenthal and Strange (2004) summarize the evidence: doubling a city’s size raises productivity by about 3 to 8 percent.
Costs of size
Bigger cities also cost more. Each new resident pushes the city edge outward, so commutes grow and land near jobs gets scarcer:
\[\text{Cost}(N) = c \cdot N^{\theta}\]
with \(\theta > \gamma\). Costs eventually grow faster than gains.
Optimal size vs equilibrium size
Utility per resident is \(U(N) = A N^{\gamma} - c N^{\theta}\). It first rises, then falls. The optimal size \(N^*\) is the peak.
But no one chooses city size. People move in as long as the city beats their outside option \(\bar{u}\). So the city keeps growing past the peak, until \(U(N) = \bar{u}\). This is why many economists argue that free migration makes cities too big. Each newcomer adds to crowding but does not pay for the crowding they cause.
#| standalone: true
#| viewerHeight: 620
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("gamma", "Gains from size (agglomeration):",
min = 0.02, max = 0.10, value = 0.06, step = 0.01),
sliderInput("cost", "Cost of crowding:",
min = 2, max = 10, value = 5, step = 0.5),
sliderInput("ubar", "What people get elsewhere (outside option):",
min = 80, max = 105, value = 96, step = 1),
uiOutput("info")
),
mainPanel(
width = 9,
plotOutput("u_plot", height = "480px")
)
)
)
server <- function(input, output, session) {
A <- 100
theta <- 0.5
model <- reactive({
g <- input$gamma
cc <- input$cost
nmax <- max(40, 3 * (A * g / (cc * theta))^(1 / (theta - g)))
N <- seq(0.05, nmax, length.out = 1500)
U <- A * N^g - cc * N^theta
n_opt <- (A * g / (cc * theta))^(1 / (theta - g))
u_opt <- A * n_opt^g - cc * n_opt^theta
# equilibrium: largest N where U >= ubar (to the right of the peak)
right <- N >= n_opt & U >= input$ubar
n_eq <- if (any(right)) max(N[right]) else NA
list(N = N, U = U, n_opt = n_opt, u_opt = u_opt, n_eq = n_eq, nmax = nmax)
})
output$u_plot <- renderPlot({
m <- model()
par(mar = c(4.5, 4.5, 3, 1))
plot(m$N, m$U, type = "l", lwd = 3, col = "#2c3e50",
xlab = "City population (millions)",
ylab = "Utility per resident",
main = "Gains minus crowding costs",
ylim = c(min(m$U, input$ubar) - 5, max(m$U) + 5))
abline(h = input$ubar, lty = 2, col = "#e74c3c", lwd = 2)
abline(v = m$n_opt, lty = 3, col = "#27ae60", lwd = 2)
points(m$n_opt, m$u_opt, pch = 19, cex = 1.6, col = "#27ae60")
if (!is.na(m$n_eq)) {
abline(v = m$n_eq, lty = 3, col = "#e67e22", lwd = 2)
points(m$n_eq, input$ubar, pch = 19, cex = 1.6, col = "#e67e22")
}
legend("topright", bty = "n", cex = 0.9,
legend = c("Utility per resident", "Outside option",
"Optimal size", "Equilibrium size"),
col = c("#2c3e50", "#e74c3c", "#27ae60", "#e67e22"),
lwd = c(3, 2, 2, 2), lty = c(1, 2, 3, 3))
})
output$info <- renderUI({
m <- model()
eq_txt <- if (is.na(m$n_eq)) {
"no city forms (outside option too good)"
} else if (m$n_eq >= 0.999 * m$nmax) {
"off the chart"
} else {
paste0(round(m$n_eq, 1), " million")
}
tags$div(class = "info-box",
HTML(paste0(
"<b>Optimal size:</b> ", round(m$n_opt, 1), " million<br>",
"<b>Equilibrium size:</b> ", eq_txt, "<br>",
"<b>Utility at optimum:</b> ", round(m$u_opt, 1), "<br>",
"<b>Outside option:</b> ", input$ubar
))
)
})
}
shinyApp(ui, server)
Things to try
- Raise the gains from size: the peak moves right and up. Stronger agglomeration supports bigger cities.
- Raise the crowding cost: the peak moves left. Better transit or more housing works like a lower crowding cost.
- Lower the outside option: the equilibrium city grows far past the optimum. When rural life is poor, people keep coming even as crowding gets worse.
- Raise the outside option above the peak: no city forms. Gains from size must beat what people can get elsewhere.
Why the model matters
The tradeoff explains a lot. It explains why cities grew when transport costs fell and factories needed many workers. It explains why some cities shrink when their main industry leaves. It also explains why policy can make cities better: anything that lowers the cost of crowding, like transit or housing supply, raises the utility of everyone in the city.
How big do cities get? Zipf’s law
Zipf’s law is a pattern in city sizes: a city’s size is roughly the largest city’s size divided by its rank.
Take a country whose largest city has 10 million people:
- The 2nd largest has about 10 ÷ 2 = 5 million.
- The 3rd has about 10 ÷ 3 ≈ 3.3 million.
- The 10th has about 10 ÷ 10 = 1 million.
So rank × size stays about the same for every city.
Why a straight line on a log scale? Size = 10 ÷ rank. Taking logs turns division into subtraction: log(size) = log(10) − log(rank). That is a straight line with slope −1. Double the rank, and size halves.
The usual explanation is Gabaix (1999). If cities grow at random rates that don’t depend on their size, and none can shrink below a small minimum, this pattern appears on its own over time.
It holds best for the largest cities. Once you include every small town it fits less well (Eeckhout 2004). George Zipf, a linguist, first found the same pattern in how often words are used.
#| standalone: true
#| viewerHeight: 560
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("top", "Population of the largest city (millions):",
min = 1, max = 30, value = 10, step = 1),
uiOutput("info")
),
mainPanel(
width = 9,
plotOutput("bars", height = "460px")
)
)
)
server <- function(input, output, session) {
pop <- reactive(input$top / seq_len(10))
output$bars <- renderPlot({
p <- pop()
par(mar = c(4.5, 4.5, 3, 1))
b <- barplot(p, names.arg = seq_along(p), col = "#2980b9", border = "white",
xlab = "Rank of the city", ylab = "Population (millions)",
main = "City population by rank", ylim = c(0, 1.15 * input$top))
text(b, p, sprintf("%.1f", p), pos = 3, cex = 0.85)
})
output$info <- renderUI({
p <- pop()
tags$div(class = "info-box",
HTML(paste0(
"<b>Largest city:</b> ", sprintf("%.1f", p[1]), " million<br>",
"<b>2nd:</b> ", sprintf("%.1f", p[1]), " / 2 = ", sprintf("%.1f", p[2]), " million<br>",
"<b>3rd:</b> ", sprintf("%.1f", p[1]), " / 3 = ", sprintf("%.1f", p[3]), " million<br>",
"<b>Rank x population:</b> ", sprintf("%.1f", p[1]), " million for every city"
))
)
})
}
shinyApp(ui, server)
Things to try
- Set the largest city to 10 million: the 2nd city has 5 million, the 3rd 3.3 million, and the 10th 1 million.
- Double the largest city to 20 million: every other city doubles too. Each city’s population is always the largest city’s divided by its rank.
Connections
- Agglomeration Economies takes apart the gains side: labor pooling, input sharing, and knowledge spillovers.
- The Monocentric City takes apart the cost side: rents and commutes rise as the city grows.
- Spatial Equilibrium explains how wages and rents adjust when people move between cities.
Did you know?
- More than half of the world’s population now lives in urban areas. The United Nations estimates the world crossed that line around 2007.
- Jane Jacobs argued in The Economy of Cities (1969) that cities came first and farming grew around them. Her idea that cities create new kinds of work is still central to urban economics.
Key papers
- Henderson, J. V. (1974). The Sizes and Types of Cities. American Economic Review 64(4). City size as a balance of gains and costs.
- Glaeser, E. L. (1998). Are Cities Dying? Journal of Economic Perspectives 12(2). Why cities survive falling transport costs.
- Gabaix, X. (1999). Zipf’s Law for Cities: An Explanation. Quarterly Journal of Economics 114(3). Random growth with a floor produces Zipf’s law.
- Davis, D. R. and Weinstein, D. E. (2002). Bones, Bombs, and Break Points: The Geography of Economic Activity. American Economic Review 92(5). Bombed Japanese cities recovered their size.
- Eeckhout, J. (2004). Gibrat’s Law for (All) Cities. American Economic Review 94(5). The pattern weakens once small towns are included.
- Rosenthal, S. S. and Strange, W. C. (2004). Evidence on the Nature and Sources of Agglomeration Economies. Handbook of Regional and Urban Economics 4. How much bigger cities raise productivity.
- Duranton, G. and Puga, D. (2020). The Economics of Urban Density. Journal of Economic Perspectives 34(3). The benefits and costs of density, measured.