Ask AI Why Customers Cancelled (Using Your Real Database)
When weekly cancellations spike, ask Claude or Cursor to read the last N cancel rows — plans, last active, stored reasons — instead of guessing. Prompts, limits, and what the data can't tell you.
Weekly report says cancellations doubled. Someone asks why.
Without live data, people guess: pricing, a bug, “seasonality.” With a database connection, you can ask a narrower question: what do the last cancel rows actually contain?
Not a crystal ball — faster triage. Claude or Cursor can read plans, timestamps, and a reason column if you stored one, and should say when you didn’t.
Pairs with weekly database reports in Claude Code: when the churn line moves, dig in. Also: staging first, don’t open every table, verify answers.
What “why” can mean in SQL
Your schema usually supports some of these — not all:
| Signal in the DB | What you can ask |
|------------------|------------------|
| cancelled_at / status | Who and when |
| Plan or price at cancel | Cheap vs expensive plans |
| last_seen_at / last login | Already gone cold vs active-then-left |
| cancel_reason / survey text | Literal reasons (messy but real) |
| Linked tickets or NPS | Only if those tables exist and are allowed |
If the only fact is status = 'cancelled', a honest answer is: “We don’t store a reason; here’s tenure and plan distribution.” Anything more is fiction.
Prompt: last 20 cancellations
Read-only database access. Inspect schema first.
Find the last 20 customers or subscriptions that cancelled or unsubscribed
(use whatever tables/columns we actually have).
For each, pull only non-sensitive fields needed for patterns:
plan, cancelled_at, created_at or tenure, last_active if present,
cancel_reason if present.
Then summarize:
- common plans
- tenure bands (e.g. <7 days, 7-30, 30+)
- whether reasons exist and what they say
- anything that looks clustered in time
Rules:
- Do not invent cancel reasons
- If emails or raw message bodies appear in the table, do not print full PII — aggregate
- Show the SQL
- If we can't define "cancelled" from the schema, stop and say what's missing
Run it once manually. Check a couple of IDs in your admin UI or Stripe. Known-answer habit still applies.
Prompt: spike week vs prior week
After a weekly report flags a jump:
Cancellations look higher this week than last week.
Using the database, compare the two weeks:
- counts
- plan mix
- share with a filled cancel_reason
- median tenure at cancel
Call out differences with numbers. If sample size is tiny, say the comparison is weak.
SELECT only. Show SQL.
Prompt: “are cancels mostly trials that never activated?”
Among cancelled accounts in the last 90 days, what share never passed
a basic activation event we store (e.g. created a project, sent a first request)?
Define activation from real event/table names after inspecting schema.
If we don't log activation, say so — don't proxy with "logged in once."
Product teams ask this constantly. The model only helps if activation is in the DB you connected.
Limits (say them out loud)
- No reason field → no mind reading. Store a reason, import Stripe’s cancellation feedback, or accept aggregate-only answers.
- PII in chat. Cancel rows often include emails. Prefer aggregates, staging, or an allowlist that exposes an anonymized view.
- Correlation ≠ cause. “Most cancels were on the $9 plan” is a fact. “Because of price” is a hypothesis — test it elsewhere.
- Warehouse vs OLTP. Heavy churn history might live in the warehouse. If Postgres is thin, don’t force MCP onto the wrong store.
Where this fits in the week
- Monday job reports cancel count (weekly reports)
- If the line moves, run the “last 20” prompt
- If reasons are empty, fix instrumentation — don’t keep asking the model for a story
- Check Usage so you know which connection answered
Better question than “why do we lose customers?”: “what’s in the cancel rows we already have?”
Safe DB at mcpserver.design, restrict tables, paste the last-20 prompt.
Related reading:
- Weekly Database Reports with Claude Code — the recurring cancel count
- Prompts for Talking to Your Database — more paste-ready prompts
- Don't Give Your AI Access to Every Table — keep full users off the connector
- Talk to Your Database Without an Analyst — ad-hoc questions
- Ask Claude About Your Database — plain English to SQL