How to Cluster 12 Months of Support Tickets in a Week
Every year, a PM decides this is the quarter they finally cluster the tickets. They export 40,000 rows to a spreadsheet, spend two weekends on it, and give up. The problem is not the size of the corpus. It is the belief that clustering starts with a taxonomy.
Here is a five-day protocol that starts with the tickets and lets the taxonomy emerge from them.
What do you need before day one?
Line up four inputs before you start. Missing any of them will cost a full day.
- Read-only API access to your ticket system (Zendesk, Intercom, Freshdesk).
- Account mapping. Every ticket must be joinable to an account in your CRM by email domain or user ID.
- A CRM export with account name and ARR (or a proxy: seat count, plan tier).
- An embeddings pipeline. Any modern text embedding API works. Do not build a bespoke model.
If you do not have ARR on the account object, use a plan-tier ranking (enterprise, mid-market, SMB, free) as a stand-in. Precision drops, but the exercise is still worth running.
Day one: how do you export and clean the corpus?
Export the full 12 months. Do not sample. Six moves get you clean data by end of day.
- Pull tickets with subject, customer body, thread messages, ticket ID, requester email, and created-at timestamp.
- Drop agent messages and internal notes. Keep only customer-written text.
- Concatenate subject and customer text into one field per ticket.
- Deduplicate on requester email plus first 100 characters of the ticket body. Support systems create duplicates from webhook retries and thread splits.
- Language filter. English-language tickets in one bucket, everything else in a second pass. Do not mix.
- Join to CRM. For each ticket, attach account name and ARR by matching requester email domain to the CRM account.
End of day one, you have a CSV with one row per ticket, cleaned, joined, and language-filtered. Row count is usually 60 to 80% of the raw export after dedup and cleaning.
Day two: how do you generate embeddings and clusters?
Two steps, both scripted, both fast.
- Embed. Run every ticket through an embedding model. Modern APIs cost roughly $0.02 to $0.10 per 1,000 tickets, which for 40,000 tickets is under $10.
- Cluster. Use HDBSCAN or a similar density-based algorithm. Aim for 30 to 80 clusters. Too few and you are back to top-level tags. Too many and the merge step tomorrow becomes intractable.
Set the minimum cluster size to about 1% of your corpus. So for 40,000 tickets, minimum cluster size is 400. Anything smaller is noise or a real but low-frequency theme that will surface on the next pass.
Do not name the clusters yet. That is tomorrow's job. Today, produce a CSV with ticket ID and cluster ID.
Day three: how do you name and merge clusters?
This is the human day. Budget eight hours. Two PMs is better than one, because you will disagree, and every disagreement is a signal.
For each of the top 30 clusters by ticket count:
- Read 20 random tickets from the cluster.
- Write a 3-to-5-word label in customer language, not internal language. "CSV export fails on big files" beats "reporting bugs."
- Split, merge, or keep. If the 20 tickets tell two stories, split. If two clusters read as one, merge. If they are one story, keep the label.
Two rules keep the day from spiraling:
- Do not create new clusters by hand. If a set of tickets does not belong in any of the top 30, they belong in a "long tail" bucket for the next pass, not a hand-carved cluster today.
- The label is quotable, always. If you cannot imagine an engineer reading the label in a Linear ticket and knowing what to build, rewrite it.
End of day three, you have 20 to 30 named clusters covering roughly 70 to 85% of the corpus.
Day four: how do you attach ARR and account weight?
For each named cluster:
- List the unique accounts whose tickets fell into the cluster.
- Sum the ARR of those accounts from your CRM.
- Count the accounts. Not the tickets, the accounts.
- Flag the top three accounts by ARR inside each cluster. These are the accounts you will name in the write-up.
- Compute quarter-over-quarter trend. Ticket count in the last 90 days versus the previous 90 days.
You now have five numbers per theme: ticket count, account count, total ARR, top-3 account ARR, and QoQ trend. This is enough to rank on multiple axes without collapsing to a single score.
Day five: how do you publish and hand off?
The output is not a spreadsheet. It is a ranked list of themes, each with:
- Theme name in customer language
- Three numbers: mentions, accounts, ARR
- Trend line: up, flat, down, with QoQ percentage
- Three named accounts and one representative quote each
- Link back to the underlying ticket IDs
Publish the top 20 themes in whatever tool your product team lives in: Notion, Confluence, Linear, Productboard. For the top five, open a Linear or Jira issue with the theme name, quotes, and account list already in the description.
The hand-off is not a slide deck. It is issues in the roadmap tool, with evidence attached.
What are the pitfalls that eat the week?
Four traps consume most first attempts.
- Designing a taxonomy first. Kills the project. Start with clustering, name later.
- Manual tagging as validation. Do not re-tag every ticket "to be sure." Trust the clustering, spot-check on day three.
- Over-splitting. More than 30 named clusters is not a taxonomy, it is a spreadsheet.
- Skipping the CRM join. Without ARR, you have a frequency ranking, not a prioritization tool. Do the join even if it is manual.
The teams that finish in a week are the ones that resist perfectionism on days three and four. Ship the 80% version, iterate next quarter.
How do you keep it current after week one?
Weekly, not daily. Two-hour maintenance loop:
- New tickets embed and cluster automatically overnight.
- New clusters (with more than a threshold count) surface in a weekly report.
- The PM decides: fold into an existing theme, promote to a new named theme, or leave as long tail.
If maintenance takes more than four hours a week, your clustering is not stable enough, and the fix is to raise the minimum cluster size, not to add tagging discipline.
The mistake to avoid
The mistake is treating this as a research project, not a product operations project. Research projects do not have deadlines and rarely publish. Product operations projects have a five-day sprint, a named owner, and a published output that changes what shows up in the next prioritization meeting. If your ticket cluster project is not on someone's Q1 goals with a specific week marked out, it will not happen this year either.
Frequently asked questions
How many tickets can we realistically cluster in a week?
With modern embedding and clustering, 50,000 to 200,000 tickets is a one-week job for a single technical PM or product ops person. The bottleneck is not compute. It is the review-and-merge step on day three, where a human has to name the clusters and decide which to split or combine. Budget that day at eight full hours.
Do we need every ticket, or is a sample enough?
Use all of them for the first pass. Sampling introduces bias toward high-frequency themes and undercounts the rare-but-high-ARR ones. Once you have a stable taxonomy, weekly sampling for maintenance is fine. The initial backfill needs to be complete or the trend lines you produce next quarter will be wrong.
What if our tickets are mostly one-line replies?
Concatenate the ticket subject, first customer message, and any thread messages the customer wrote (skip agent messages). Short messages cluster fine as long as the embedding model sees the subject too. Ignore tickets where the customer never wrote anything, they are usually agent-initiated and not feedback.
Should we strip agent responses from the corpus?
Yes, always. Agent responses will pull clusters toward canned language and internal terminology, which distorts what customers actually said. Keep only customer text. If your embeddings service has a language filter, use it, because non-English tickets should be handled in their own cluster pass unless volume is trivial.
How do we validate the clusters are 'right'?
Two tests. First, a PM reads a random 30 tickets inside each of the top 10 clusters, and 90% of them fit the label the PM would use. Second, another PM re-labels the top 10 clusters cold and agreement is at least 80%. If either fails, split the failing clusters and re-run.
Price every roadmap debate in ARR
Palarel clusters every ticket, call, review, and survey into ranked themes with the accounts and revenue behind each one, then files the evidence in your roadmap tool.
Request early access