# Open-source churn signals: three systems, one ranked list

> Churn signals are behavior changes that come before an account cancels. One on its own is noise; the accounts worth calling are where two or three agree. Kortix is the open-source CompanyOS: your agents, their skills, your company memory, and every connector in one git repo you own, with the agents working on real cloud computers.

URL: https://churnpredictionguide.com/churn-signals

## The five rules the agent loads before every scan

`skills/churn-signals/SKILL.md`

```
- Usage is declining when core activity drops 20% or more against the prior 30 days, and dormant after 14 days with almost no activity.
- Support friction is rising when thread volume climbs above the account's history or threads stay unresolved. Cancellation language counts as escalated.
- Billing is at risk after a missed or failed payment. A renewal is imminent within 30 days.
- No single signal is high risk on its own. Rank accounts with declining usage, rising support friction and an imminent renewal or failed payment first.
- Give every listed account a reason and one next step. Never write to Postgres, Plain or Stripe, and never contact a customer.
```

Source: https://kortix.com/markdown/use-cases/churn-risk.md

The churn-signals rule set as the churn-risk setup holds it, thresholds and combination rule included.

## A churn signal is a change before it is a prediction

Every churn signal is a fact about the present that a team reads as a guess about the future. An account that used the product heavily in March and less in April may be leaving, or may have finished the project it bought the product for. A support thread that runs long may mean a team in trouble. It may also mean a support queue sat on a simple question for a week. The measurement is real either way. Its meaning is not settled by the measurement alone.

A churn signal is, by definition, a measured change in an account's usage, support behavior or billing state that tends to come before a cancellation. Usage decline, dormancy, an escalated support thread, a failed payment and an approaching renewal all qualify. None of them is a forecast by itself, and a list built from one of them is mostly wrong in a way that looks precise.

The accounts worth calling are the ones where two or three independent systems agree inside the same month. A dashboard that draws on one system cannot produce that list, however good its chart.

## The readings, and the false positive inside each

### Usage: a 20% drop against the prior 30 days

Product usage lives in the product database. The churn-risk skill's rule for it is one line: usage is declining when core activity drops 20% or more against the prior 30 days. A fall that size across a month is hard to produce by accident, which is why the threshold holds up. The number still cannot tell a team that left from a team that finished. A seasonal dip, a pilot that ended on the date it always would, a customer whose heavy manual exports stopped because an integration replaced them: each produces the drop without producing the risk. The signal opens a question and leaves it open.

### Dormancy: 14 days with almost no activity

The same rule continues: an account is dormant after 14 days with almost no activity. Dormancy is the earliest reading in the set and the noisiest. Annual contracts go quiet between projects. Work moves to a sibling workspace and the activity starts appearing under another account. A shutdown period looks exactly like a team that has quietly left. Read alone, dormancy mostly means someone should go and look.

### Support: rising volume, unresolved threads, the word cancel

A support inbox holds the third reading. Support friction is rising when thread volume climbs above the account's history or threads stay unresolved, and cancellation language counts as escalated. Support data carries its own trap. In a small account, one angry person can generate most of the volume, and that person is often not the buyer. A thread can also stay open because the vendor's queue is slow, which is a fact about the vendor and not about the account. Cancellation language is the strongest single item in the set. Even that line shows up in a procurement email testing an exit clause during a renewal.

### Billing: a failed payment, or a renewal inside 30 days

Payment status and renewal dates sit in the billing system. Billing is at risk after a missed or failed payment, and a renewal is imminent within 30 days. Failed payments clear on their own often enough that a finance team will wave them through: a card gets reissued, dunning succeeds on the third attempt, a renewal auto-closes without a conversation. What makes the billing reading valuable is its origin. It comes from a system that records money rather than behavior, so when it agrees with usage and support, the agreement is not an artifact of one table.

## Why the three systems rarely meet

Product usage lives in the product database, support in the inbox, money in billing. In the example stack that the Kortix churn-risk setup connects, those are Postgres, Plain and Stripe, with the ranked list landing in Slack; a team swaps in whatever holds the same records. Nobody designed that split for churn detection. What it costs is the join. Three credentials, three schemas, and an account key that is a UUID in one system, a domain in another and a customer ID in the third. Someone has to own that mapping. In most companies nobody does, so the correlation happens in a spreadsheet the week before a quarterly review.

Tools that offer to do the work usually see one side of it. A usage dashboard shows a drop and leaves the reader to open the inbox. A health score inside a customer-success platform is computed from whatever feed it was given, and the feed is often a partial sync of the product data. Manual reviews do combine everything, and they run quarterly, by which point the first signal is two months old.

## The combination rule

The churn-risk skill writes the combination down so that two people reading the same data reach the same list. No single signal is high risk on its own, and accounts with declining usage, rising support friction and an imminent renewal or failed payment rank first.

The reasoning matters more than the wording. Each reading carries its own false positive rate, and the false positives do not line up, because the systems record different things. A seasonal dip in the product database has nothing to do with a reissued credit card. When one system fires, the chance the account is leaving is modest. When three fire in the same window, every one of them has to be wrong at once, and the chance that a person should pick up the phone is high.

The ordering follows from the same logic. An account with two agreeing signals earns a place on the list. An account with one belongs on a watch list, where someone checks it when the work is done.

## One month, three accounts

Northwind, Globex, Initech and Vandelay are placeholders, and the figures are illustration, not a customer result.

- **Northwind.** Core usage down 27% against the prior 30 days, an escalated support thread that names cancelling, renewal in 19 days. Three systems agree, so Northwind ranks first. Its reason reads "usage down 27%, cancellation language in support, renewal inside 30 days". The next step is "renewal conversation with the account owner this week."
- **Globex.** Usage flat, two threads unresolved for nine days, a failed payment six days ago. Two readings agree while usage contradicts them, so Globex lands second: "failed payment, two open threads; check the card, then ask about the open tickets."
- **Initech.** Usage down 34%, no support activity, next renewal in seven months. One signal only, so Initech stays off the call list and goes to the watch list, where a usage drop with nothing behind it is the most common false positive in the set.

A fourth account shows the rule working in the other direction. Vandelay has been dormant for 16 days and nothing else has fired, which usually means a quiet quarter or work that moved to a sibling workspace. Vandelay stays off the list too, and the list stays short enough for someone to read.

## What the list has to hand back

Every listed account gets a reason and one next step. The ranking is the least useful column. A reason lets the account owner disagree with the system, and the disagreement is the fastest way to find a threshold that is wrong. A next step turns the list into Monday's work, and the last line of the skill carries the boundary with it: a reason and one next step for every account named, and no write to Postgres, Plain or Stripe.

The reasons also compound. After a few months, the accounts that did churn can be read back against the signals that fired for them. A rule that produced mostly noise gets changed in the skill file and reviewed like any other change. The [churn risk scoring rules](/churn-risk-scoring) cover how to tune one without guessing. Five people can argue about a document. The argument is how the thresholds improve.

## Running the read on your own systems

On [Kortix](https://kortix.com/use-cases/churn-risk), the rules, the agent and the schedule are files in a repo the company owns, which is what makes a threshold editable without a vendor ticket. A cron trigger starts the scan every day at 06:00 UTC.

```yaml
triggers:
  - slug: daily-churn-scan
    name: Daily churn-risk scan
    on:
      cron: "0 0 6 * * *"
    run:
      agent: churn-risk
      prompt: Load the churn-signals skill and run one complete churn-risk scan.
```

The schedule is a cron line a person can read, and the run names the agent and its prompt. The agent loads the skill, reads the three systems, and posts one message to the team channel. One isolated sandbox per session. Each session has its own isolated machine and branch. Connector credentials are brokered server-side and never enter the machine.

The connectors into Postgres, Plain and Stripe are read-only in this setup. A wrong score costs a call. It cannot change a subscription, close a ticket or email a customer, which keeps the false positive a nuisance rather than an incident.

## Churn signals, asked and answered

### What does churn mean in corporate speak?

Churn is the share of accounts or revenue a company loses over a period, usually the customers who cancelled or did not renew. Teams say an account churned, or quote a rate such as 3% monthly churn, and the number usually leaves out new sales that offset it.

### What is a leading indicator of churn?

A leading indicator of churn is a measured change that appears before an account cancels. Usage down 20% or more against the prior 30 days, 14 days of dormancy, an unresolved or escalating support thread, a failed payment and a renewal inside 30 days all count.

### How far ahead can you see churn?

Days to a few weeks for most accounts. A usage decline or a support thread that turns sharp usually shows weeks before a cancellation, while a renewal inside 30 days or a failed payment sets a firm horizon. Dormancy shows earliest, at 14 days.
