Why sinks hold high density

ecology tutorial
R
population ecology
conservation
habitat selection
Why a sink can hold more animals than the source that feeds it, worked in R, and why population density is a treacherous guide to habitat quality.
Author

Tidy Ecology

Published

2026-07-31

The previous post ended on a warning: a habitat’s local growth rate tells you whether it can sustain itself, not how many animals it holds. This post makes that concrete with the result that most surprises people the first time they meet it. At equilibrium a sink can hold more individuals than the source that keeps it alive. The worst habitat on the landscape can be the most crowded.

The arithmetic of the paradox

A source at equilibrium is capped. It has a fixed number of breeding sites, and once they are full the extra production has nowhere to go but out, so the source sits at its own capacity and exports the rest. A sink has no such cap from below: it keeps accepting immigrants, and its population climbs until the annual shortfall between births and deaths, which grows with population size, finally balances the steady inflow. That balance point is the immigration divided by the per-capita shortfall.

l1 <- 1.5; l2 <- 0.84; n1 <- 100          # source growth rate, sink growth rate, source size
surplus <- n1 * (l1 - 1)                    # emigrants the source sends each year
n2 <- surplus / (1 - l2)                    # equilibrium sink size
c(source_size = n1, sink_size = n2, ratio = n2 / n1)
source_size   sink_size       ratio 
    100.000     312.500       3.125 

The source holds 100 breeding adults and exports 50 surplus animals a year. The sink, losing 16 per cent of its population to the shortfall each year, swells until that loss equals the inflow, which happens at 312, more than 3.1 times the source. Stand in each habitat and count: the sink looks like the stronghold and the source like the marginal patch. The count has it exactly backwards.

dp <- data.frame(habitat = c("source\n(grows locally)", "sink\n(shrinks locally)"),
                 N = c(n1, n2), kind = c("source", "sink"))
ggplot(dp, aes(habitat, N, fill = kind)) +
  geom_col(width = 0.6) +
  scale_fill_manual(values = c("source" = col_source, "sink" = col_sink), guide = "none") +
  labs(x = NULL, y = "Standing population", title = "The worst habitat holds the most animals")
Two bars: a short green source bar and a much taller ochre sink bar, with labels noting the source grows and the sink shrinks locally.
Figure 1: Standing population in the source and the sink. The sink (ochre, local growth rate below one) holds several times the source (green, local growth rate above one) that produces every surplus animal it receives.

Density is a trap for the manager

Now put the whole landscape together: many habitats of different quality, some sources, some sinks, all connected by movement. Plot the standing density in each against its local growth rate, the real measure of quality.

set.seed(408)
imm <- 40
habitat <- data.frame(lambda = seq(0.5, 1.5, length = 25))
habitat$density <- ifelse(habitat$lambda >= 1, 80 + rnorm(25, 0, 4),   # sources capped
                          pmin(imm/(1 - habitat$lambda), 400))          # sinks pile up near lambda = 1
c(correlation_density_quality = cor(habitat$lambda, habitat$density))
correlation_density_quality 
                 -0.2646964 

The correlation between density and quality is -0.26: if anything, slightly negative. The three most crowded habitats have local growth rates of 0.92, 0.96 and 0.88, every one of them a sink. A conservation plan that ranks habitats by how many animals they hold, a natural and common thing to do, will pour effort into the crowded sinks and neglect the sparse sources that are quietly producing the entire population (Van Horne’s warning, and the reason Pulliam 1988 The American Naturalist 132(5):652-661 mattered so much). Protect the sink and you protect a display; protect the source and you protect the supply.

habitat$kind <- ifelse(habitat$lambda >= 1, "source", "sink")
ggplot(habitat, aes(lambda, density, colour = kind)) +
  geom_vline(xintercept = 1, colour = col_ref, linetype = "dashed") +
  geom_point(size = 2.6) +
  scale_colour_manual(values = c("source" = col_source, "sink" = col_sink)) +
  labs(x = "Local growth rate (habitat quality)", y = "Standing density", colour = NULL,
       title = "Density does not measure quality")
Scatter of density against local growth rate; the highest densities occur at growth rates below one, and habitats above one are only moderately dense.
Figure 2: Standing density against local growth rate across a landscape of habitats. Density does not track quality: the densest habitats (ochre, sinks) grow less than one, while the true sources (green) can be sparse.

When the pattern appears, and when it does not

This upside-down world is not guaranteed; it depends on how animals settle. If they distribute themselves to equalise their prospects, filling the good habitat first and spilling into the poor one only when the good one is crowded, the sink stays empty until the source is full, and it never gets absurdly crowded. The extreme version here, where the sink dwarfs the source, needs animals that keep settling in the sink regardless, either because they cannot tell it is poor or because they are forced there. That is exactly the setting where a habitat can become a trap, luring settlers into a patch that quietly kills them, which is the next post. And because density has now failed twice as a guide to quality, the checking post turns to what you actually have to measure.

References

  • Pulliam HR 1988. The American Naturalist 132(5):652-661 (10.1086/284880).

Newsletter

Get new tutorials by email

New R and QGIS tutorials for ecologists, straight to your inbox. No spam; unsubscribe anytime.

By subscribing you agree to receive these emails and confirm your address once. See the privacy policy.