CountLineage

RFM segmentation

AI for data and analytics · Facts checked 28 October 2026

RFM segmentation groups customers by three facts from their order history: recency (days since their last purchase), frequency (number of orders) and monetary value (total spend). Each is scored, usually 1 to 5 by quintile, and the three scores combine into a code such as 545 that maps to a named segment like Champions or At risk.

What is RFM segmentation?

RFM comes from direct mail, where catalogue companies had to decide who got the next expensive mailing. Three facts from the order history did most of the work: how recently someone bought, how often, and how much. Arthur Hughes' Strategic Database Marketing (first published 1994) popularised the version most teams still use: score each of the three in quintiles, 1 to 5, and you get 125 cells from 111 to 555.

  • Recency: days since the customer's last order, counted back from a fixed analysis date. Fewer days scores higher.
  • Frequency: number of orders in the window. More scores higher.
  • Monetary: total spend in the window (some teams use average order value). More scores higher.

RFM ranks customers by what they have done. It doesn't forecast what they'll do. Fader, Hardie and Lee's 2005 paper RFM and CLV is the standard bridge between the two: it uses the same three inputs in a probability model to estimate each customer's future value, and shows that customers with quite different RFM histories can be worth the same. If the question is "how much is this customer worth?", that's lifetime value. If the question is "who should get which email?", RFM is usually enough.

How to score RFM with quintiles

Quintile scoring sorts customers on each measure separately and splits them into five equal groups. IBM's SPSS Modeler calls this independent binning: each measure is ranked without regard to the other two. Here bin 5 is the best: most recent, most frequent, highest spend.

A worked example

Ten customers of an online shop, scored on 1 October 2026 over the previous 12 months. With ten customers, each quintile holds two. The figures are invented to show the method.

Customer Days since last order Orders Spend R F M Code Segment
A 5 12 £1,840 5 5 5 555 Champions
B 12 8 £960 5 4 4 544 Champions
C 20 3 £410 4 3 3 433 Loyal
D 34 6 £1,120 4 4 4 444 Champions
E 48 2 £150 3 2 2 322 New or recent
G 110 1 £60 3 1 1 311 New or recent
H 160 4 £520 2 3 3 233 At risk
F 200 9 £2,300 2 5 5 255 At risk
I 240 1 £95 1 1 1 111 Lost
J 300 2 £180 1 2 2 122 Lost

Recency first. Sorted by days since the last order, A and B (5 and 12 days) are the most recent fifth and score 5; I and J score 1. Frequency and monetary are sorted the other way, so F's nine orders and £2,300 put F in the top fifth on both.

Customer F is why people use RFM. On spend alone F is the best customer in the table. On RFM, F is a 255: valuable, and gone quiet for 200 days. That's a different email from the one A should get.

Note what the scores are: ranks within this group of customers at this date. A 5 for recency means "in the most recent fifth", not "bought within a week". Rescore next month and the cut-offs move.

See which orders put each customer in a segment

Connect your warehouse or order export, ask Count in plain English, and open the Reasoning Chain behind every segment: which orders, which refunds, which window.

The named RFM segments

Codes like 255 are hard to act on, so teams group them into named segments. There is no standard list. Names, the number of segments and the score rules all vary by tool and by author, so treat any table of segments, including this one, as a starting point.

The rules used in the example above, applied in this order:

Segment Rule Usual action
Champions R ≥ 4 and F ≥ 4 Early access, referrals, no discounts needed
Loyal R ≥ 3 and F ≥ 3 Cross-sell, loyalty perks
New or recent R ≥ 3, F ≤ 2 Second-order nudge
At risk R ≤ 2 and F ≥ 3 Win-back, personal outreach for high M
Needs attention R = 2, F ≤ 2 Reminder, light offer
Lost R = 1, F ≤ 2 Low-cost reactivation, or stop mailing

For comparison, Klaviyo's RFM report scores each measure 1 to 3 rather than 1 to 5, and uses six groups: Champions, Loyal, Recent, Needs attention, At risk and Inactive, each defined by its own list of score combinations. Its At risk is a customer who hasn't bought recently with a low or medium spending score, which isn't quite the rule above. Same names, different customers. If two teams compare segment sizes, compare the rules first.

RFM in SQL with NTILE

Most warehouses can do this in one query. Here is a short orders table:

order_id customer_id order_date amount status
1001 A 2026-09-26 160.00 completed
1002 F 2026-03-15 240.00 completed
1003 G 2026-06-13 60.00 completed
1004 I 2026-02-03 95.00 completed
1005 E 2026-08-14 70.00 refunded

The query below is PostgreSQL (subtracting two dates gives days; in BigQuery use DATE_DIFF). It builds one row per customer, scores each measure with NTILE(5), then names the segment.

WITH customers AS (
  SELECT
    customer_id,
    DATE '2026-10-01' - MAX(order_date) AS days_since_last,
    COUNT(DISTINCT order_id)            AS orders,
    SUM(amount)                         AS spend
  FROM orders
  WHERE status = 'completed'
    AND order_date >= DATE '2025-10-01'
    AND order_date <  DATE '2026-10-01'
  GROUP BY customer_id
),
scored AS (
  SELECT
    *,
    NTILE(5) OVER (ORDER BY days_since_last DESC) AS r,
    NTILE(5) OVER (ORDER BY orders)               AS f,
    NTILE(5) OVER (ORDER BY spend)                AS m
  FROM customers
)
SELECT
  CASE
    WHEN r >= 4 AND f >= 4 THEN 'Champions'
    WHEN r >= 3 AND f >= 3 THEN 'Loyal'
    WHEN r >= 3            THEN 'New or recent'
    WHEN f >= 3            THEN 'At risk'
    WHEN r = 2             THEN 'Needs attention'
    ELSE 'Lost'
  END                      AS segment,
  COUNT(*)                 AS customers,
  SUM(spend)               AS spend
FROM scored
GROUP BY 1
ORDER BY 2 DESC;

Recency sorts by days descending, so the customers who bought longest ago land in bucket 1 and the most recent in bucket 5. Frequency and monetary sort ascending for the same reason. On the ten customers above it returns Champions 3, Loyal 1, New or recent 2, At risk 2, Lost 2.

NTILE splits rows as evenly as it can. BigQuery's documentation says bucket sizes differ by at most one, with the remainder going to the lowest buckets first. That evenness is exactly the problem with frequency, as the next section explains.

Traps that make RFM scores wrong

The time window. Lifetime data lets a customer who bought weekly in 2019 score 5 on frequency today. A 12-month window fixes that, but it also caps frequency and drops anyone whose last order fell outside it, so they vanish from Lost rather than appearing in it. Pick the window on purpose, fix the analysis date in the query instead of using CURRENT_DATE, and write both in the output.

Returns and refunds. An order returned in full should count towards neither frequency nor spend. Net partial refunds off the amount. Klaviyo's RFM report, for example, only counts orders with a positive value, so fully discounted orders are left out. If refunds sit in a separate table, join them before you aggregate, or a serial returner will look like a Champion.

One-off B2B orders. A single £40,000 wholesale order makes a customer an M of 5 and an F of 1, and drags the monetary cut-offs up for everyone else. Score trade accounts separately, or score at the company level rather than per contact, and look at the top ten spenders by hand before trusting the cut-offs.

Ties in NTILE. In a shop where most customers have bought once, NTILE still makes five equal groups, so identical one-order customers get split across buckets 1, 2 and 3 by whatever order the database happens to return them in. PostgreSQL's documentation only promises that NTILE divides the rows "as equally as possible"; BigQuery's own example shows tied rows landing in different buckets. Run it twice and a customer can change segment without placing an order. Two fixes:

  • Use fixed thresholds for frequency: 1, 2, 3 to 4, 5 to 9, 10 or more orders.
  • Use CEIL(5 * CUME_DIST() OVER (ORDER BY orders)). Peers (rows with equal values) always get the same CUME_DIST, so ties stay together. The buckets come out uneven, which is the honest result.

Duplicate customers. Guest checkouts and changed email addresses split one person into several low scorers. Deduplicate before scoring.

Comparing months. Because quintiles are relative, the share of customers scored 5 stays at roughly a fifth whatever happens. To track whether more customers are lapsing, fix the cut-offs once and reuse them.

Asking Claude to build your RFM segments

Claude writes RFM SQL quickly. Left to itself, it will also pick the window, ignore refunds, use NTILE on a frequency column that is mostly ones and present the segment counts without saying any of that. The fix is to make each of those choices yours, and to make it show the counts at every step. More on that pattern in text-to-SQL and prompts for data analysis.

With Count's MCP server connected, Claude can run the query against your warehouse or spreadsheet itself and show the SQL behind every number. Paste this and fill in the brackets:

Build RFM segments from [schema.orders] in [warehouse].
Read only. Analysis date: [2026-10-01]. Window: the 12 months before it.

1. Before writing SQL, tell me which columns you'll use for customer,
   order ID, order date, amount and status, and the grain of the
   table (one row per what). Ask me if any is unclear.
2. Exclude cancelled and fully refunded orders, and net partial
   refunds off the amount. Report how many orders and how much
   revenue each exclusion removed.
3. Show how many customers have 1, 2, 3, 4 and 5+ orders. If more
   than 20% share one value, score frequency with
   CEIL(5 * CUME_DIST() OVER (ORDER BY orders)) instead of NTILE,
   and say so.
4. Score recency, frequency and monetary 1 to 5, with 5 the best.
5. Name segments with exactly these rules, in this order:
   [paste your rules]
6. Run it. Show one table: segment, customers, share, total spend,
   median days since last order.
7. List the 10 highest spenders with their orders and scores, and
   flag any single order over [£ amount].
8. Show every query in full, with the row count after each step.

Step 7 catches the B2B order and the refund you forgot. Step 3 catches the ties. If the segment counts change when you run it twice, step 3 wasn't followed.

In Count, every segment count comes with its Reasoning Chain: the query, the filters and the orders behind it. When the CRM team asks why a customer is At risk, you can show them which orders put them there. For using the segments in your CRM, see AI for CRM data.

Sources

  1. Hughes, Strategic Database Marketing (McGraw-Hill; first published 1994)
  2. Fader, Hardie and Lee (2005), RFM and CLV: Using Iso-Value Curves for Customer Base Analysis
  3. IBM Documentation: RFM Analysis node
  4. Klaviyo Help Center: Understanding scoring and customer groups in the RFM report
  5. PostgreSQL Documentation: Window functions
  6. Google Cloud: BigQuery numbering functions (NTILE)

Early access

Count Lineage isn't ready to download yet.

Count Lineage is coming to Claude Desktop in the next few weeks. Leave your work email and we'll send you the download the day it's ready.

Where should Lineage go after Claude? Optional

One email when it's ready. No newsletter.