Case Study 8.2 — One Matrix, Many Months: A Subscription Business as a Markov Chain

Field: data science / business economics.

A subscription company — a streaming service, a SaaS product, a gym — lives and dies by a single question: of the customers it has today, how many will still be paying next month, and the month after, and a year from now? Remarkably, the whole forecast reduces to one matrix and the operations of Chapter 8. Each customer is in one of a few states (active, cancelled), a transition matrix advances the population one month, and matrix multiplication — specifically, powers of that matrix — jumps the forecast forward any number of months at once. This case study builds the model from scratch, shows how $P^n$ predicts the long run, and uses non-commutativity to answer a real strategic question: does it matter when you run a retention promotion?

The transition matrix

Keep it to two states: Active (paying) and Cancelled (churned). Suppose that, in a typical month, $85\%$ of active customers stay active and $15\%$ cancel, while $10\%$ of cancelled customers reactivate and $90\%$ stay gone. Collect these into a matrix $P$ whose columns describe "where does each group go?" — exactly the columns-as-images reading from Chapter 7, now applied to populations:

$$P = \begin{bmatrix} 0.85 & 0.10 \\ 0.15 & 0.90 \end{bmatrix} \begin{array}{l} \leftarrow \text{end Active} \\ \leftarrow \text{end Cancelled} \end{array}$$

The first column $(0.85, 0.15)$ says "of the currently active, $85\%$ stay active and $15\%$ become cancelled"; the second column $(0.10, 0.90)$ says the same for the currently cancelled. Each column sums to $1$, because every customer goes somewhere — this is what makes $P$ a column-stochastic matrix, the defining feature of a Markov chain. (Some texts put the probabilities in rows instead; we use columns so that advancing the state is a clean matrix-times-vector $\mathbf{x}_{\text{next}} = P\mathbf{x}$, consistent with the rest of this book.)

If the state vector $\mathbf{x} = (\text{active}, \text{cancelled})$ holds today's customer counts, then next month's counts are $P\mathbf{x}$ — and that product is, by Chapter 7, the weighted sum of $P$'s columns, blending the two groups' destinations.

Stepping forward one month at a time

Start a cohort of $1000$ active customers and none cancelled, $\mathbf{x}_0 = (1000, 0)$, and step:

# March a Markov chain forward by repeated matrix-vector multiplication.
import numpy as np
P = np.array([[0.85, 0.10], [0.15, 0.90]])   # columns sum to 1 (column-stochastic)
x = np.array([1000.0, 0.0])                  # 1000 active, 0 cancelled
for month in range(1, 4):
    x = P @ x                                # advance one month
    print(f"month {month}:", np.round(x, 2).tolist())
month 1: [850.0, 150.0]
month 2: [737.5, 262.5]
month 3: [653.12, 346.88]

After one month, $850$ remain (the $15\%$ churn cost us $150$); after three months, only $653$ of the original cohort are still active and $347$ have churned. Each step is one multiplication by $P$ — one composition of the monthly transition with the running state.

Powers of the matrix: jumping ahead in one shot

Here is where Chapter 8's multiplication earns its keep. Stepping three months is $P(P(P\mathbf{x}_0)) = P^3\mathbf{x}_0$, so the matrix $P^3$ is the three-month transition all by itself — apply it once and you skip straight to month three. By associativity, $P^n$ is the $n$-month transition for any $n$. We can compute the matrix once and reuse it:

# P^n is the n-month transition. Compute it once; apply in a single step.
import numpy as np
P = np.array([[0.85, 0.10], [0.15, 0.90]])
x0 = np.array([1000.0, 0.0])
print("P^2 =", np.round(P @ P, 4).tolist())             # the two-month transition matrix
print("P^3 @ x0 =", np.round(np.linalg.matrix_power(P, 3) @ x0, 2).tolist())
P^2 = [[0.7375, 0.175], [0.2625, 0.825]]
P^3 @ x0 = [653.12, 346.88]

The one-shot $P^3\mathbf{x}_0$ gives $(653.12, 346.88)$, matching the three-month loop exactly — but as a single matrix application. The entry $(P^2)_{12} = 0.175$ reads as "a customer who is cancelled now has a $17.5\%$ chance of being active two months from now." This is the discrete-time heartbeat of dynamics: one matrix, raised to a power, advances a whole population through time. It is the same engine behind Google's PageRank (Chapter 29), which raises a web-link transition matrix to a high power to find where a random surfer spends its time.

The long run: where does everyone end up?

Keep multiplying by $P$ and the state settles toward a fixed distribution — the steady state — where churn out of "active" exactly balances reactivation back in. Iterating many times:

# Repeatedly apply P to find the long-run (steady-state) distribution.
import numpy as np
P = np.array([[0.85, 0.10], [0.15, 0.90]])
x = np.array([1000.0, 0.0])
for _ in range(500):
    x = P @ x
print("steady-state counts:", np.round(x, 2).tolist())
print("steady-state fraction:", np.round(x / x.sum(), 4).tolist())
steady-state counts: [400.0, 600.0]
steady-state fraction: [0.4, 0.6]

In the long run the cohort settles to $40\%$ active and $60\%$ cancelled, regardless of where it started — a sobering forecast that says this retention/reactivation balance cannot sustain more than $40\%$ of customers. That steady state is in fact a special vector of $P$: a vector that $P$ leaves unchanged (up to its total), which is an eigenvector with eigenvalue $1$ — the central object of Chapter 23 and the precise tool for computing long-run behavior without brute-force iteration. The long-run question "where does $P^n$ send everything as $n\to\infty$?" is answered by the eigenvalues of $P$, the largest of which is $1$ for any column-stochastic matrix (a fact named for Perron and Frobenius).

Does the order of promotions matter? (Non-commutativity in strategy)

Now a question only Chapter 8 can answer cleanly. Suppose that in one month the company runs a retention promotion, modeled by a better transition matrix $Q = \begin{bmatrix}0.95 & 0.30 \\ 0.05 & 0.70\end{bmatrix}$ (higher retention, more reactivation). Over a two-month window with one normal month ($P$) and one promo month ($Q$), does it matter whether the promo comes first or second? Algebraically: is $PQ = QP$?

# Two policies over two months: promo-then-normal (PQ) vs normal-then-promo (QP).
import numpy as np
P = np.array([[0.85, 0.10], [0.15, 0.90]])   # normal month
Q = np.array([[0.95, 0.30], [0.05, 0.70]])   # promo month
x0 = np.array([1000.0, 0.0])
print("PQ @ x0 (promo first, then normal) =", np.round(P @ Q @ x0, 2).tolist())
print("QP @ x0 (normal first, then promo) =", np.round(Q @ P @ x0, 2).tolist())
PQ @ x0 (promo first, then normal) = [812.5, 187.5]
QP @ x0 (normal first, then promo) = [852.5, 147.5]

The two orders give different outcomes — $812.5$ active if the promo runs first, $852.5$ if it runs second — because $PQ \ne QP$. Running the promotion in the second month retains about $40$ more customers from this cohort. The intuition: a retention promo works on whoever is active at that moment, so it is more valuable applied to the larger active base you still have after fewer normal-churn months — here, running it later (before less attrition has compounded against it within the window) keeps more people. Whatever the business explanation, the mathematical fact is the chapter's headline: the order of two transformations changes the result. A strategy team that assumes "two months, one promo — the timing washes out" is implicitly (and wrongly) assuming matrices commute.

The takeaway

A subscription business is a Markov chain, and Chapter 8 supplies its entire arithmetic. A single transition matrix $P$ encodes one month of customer flow; matrix-vector multiplication advances the population; powers $P^n$ leap forward $n$ months in one step (and point toward the steady-state eigenvector of Chapter 23); and non-commutativity means the sequence of policies — when you run the promotion — genuinely changes the outcome. The same structure models inventory, credit-risk migration, disease spread, and population ecology. Learn the operations once on a $2\times 2$ matrix, and you can forecast any system that moves through states one step at a time.