How to Find Duplicate Issues in Jira Automatically
Why searching by title never works, and what actually does

Jira suggests similar items when you create one, but nothing helps with the backlog you already have, and requests arriving by email never pass through that check. Here is what JQL and Automation can do, and where they stop.
Merging duplicates is the easy part
Most teams looking for a solution to duplicate issues in Jira start by asking how to merge them. That is the wrong end of the problem.
Merging two issues is mechanical. You copy the description, forward the comments, move the attachments, close the source. It takes a minute, and several Marketplace apps do it well.
The expensive part happens before that. Someone has to notice that BUG-317 and BUG-482 describe the same thing. On a backlog of two hundred open items, nobody notices. The duplicate lives on, two people work it in parallel, and the customer who reported it twice gets two different answers.
What Jira gives you natively
More than it used to, and less than you need.
Create a work item through the Jira interface and you will often be shown a short list of possibly related items before you submit. It is genuinely useful, and it prevents a share of duplicates at the door.
It has three limits, and they compound.
It only fires at creation time. It says nothing about the two hundred items already sitting in your backlog, which is where most of your duplicates are today.
It is a suggestion to the person typing, who is free to ignore it, and who usually does when a production incident is live and speed matters more than tidiness.
And it requires someone typing in the Jira interface. On a Service Management project, requests arrive by email and through the portal. Those never pass through that dialog, so no suggestion is ever shown, to anyone. That is precisely the channel where duplicates are most common, because a customer replying without the issue key in the subject silently opens a second request.
Beyond that, everything native is about recording a duplicate, not finding one. The Duplicate link type stores a relationship you have already identified, and there is no merge action at all.
The JQL approach, and where it stops
The obvious first move is a filter on the summary field:
project = SUP AND summary ~ "login" AND status != Done
This works, and it is worth having as a saved filter. But it depends entirely on you guessing the right word. If the original ticket says "cannot sign in" and the new one says "login broken", your search for "login" returns one of the two.
You can widen it with text ~ to cover description and comments, which helps and also floods you with unrelated matches. There is no threshold you can set that gives you precision and recall at the same time, because the query has no notion of how similar two issues are. It only knows whether a word is present.
The Automation approach, and where it stops
The next move is a rule on Issue created that compares the summary against recent issues, adds a Duplicate link and transitions the new one to Resolved.
This is a reasonable rule to build, and for a narrow case it earns its place. If your duplicates come from a monitoring system that always writes the same subject line, exact matching will catch them.
It stops in two places.
First, it matches strings, not meaning. Two tickets phrased differently by two different people never match, and those are the majority.
Second, even when it fires correctly, it cannot bring the conversation across. It closes the duplicate, and the reporter keeps replying to the closed one. Your agents are watching the surviving ticket, the customer is talking to the dead one, and nobody notices for three days.
Why this is genuinely hard
Consider two tickets opened twenty minutes apart:
SUP-411 Server returns 500 on checkout
SUP-419 Site is down, cannot place orders
Same incident. Zero shared words, apart from stopwords. No summary comparison, no JQL filter, no exact-match Automation rule will ever connect them.
Now the opposite case:
SUP-502 Login page not loading for user in Germany
SUP-503 Login page not loading after password reset
Nearly identical wording. Two completely different bugs. A rule that matched the first pair aggressively enough would merge these two by mistake, which is worse than missing a duplicate, because merging is not reversible.
Any approach based on matching words is caught between these two failures.
What better detection actually looks like
The technique that handles this is older than the current wave of AI, and it does not require sending your issue data anywhere. It is called TF-IDF, and the idea is simple enough to explain in a paragraph.
Instead of treating every word as equally meaningful, you weight each one by how rare it is in your project. In a support project for a payment product, the word "payment" appears in nine tickets out of ten and tells you nothing. The word "3DS" appears in four, and two tickets that share it are almost certainly related.
The important part is that the weighting is learned from your own backlog, not from a generic dictionary. Your vocabulary is not the same as another team's. Once a project has enough history, the engine knows which of your words carry signal.
That still will not connect "server 500" to "site is down", because no token is shared. Nothing lexical will. But it catches the large middle ground that exact matching misses, which in practice is most of your duplicates.
The Service Management case
On a JSM project the problem changes shape. Duplicates rarely come from two people deciding to open a ticket. They come from email: a customer replies without the issue key in the subject, and Jira creates a new request.
Two consequences follow.
The duplicates arrive in bursts around an incident, so detection matters more, not less.
And closing them silently is actively harmful. The reporter of the closed request has no idea where the conversation moved. Whatever you use, make sure the duplicate gets a public comment pointing at the surviving request before it is closed.
Where this leaves you
If your duplicates are machine generated with a predictable subject, build the Automation rule. It costs an hour and it will hold.
If they are written by humans, no rule will keep up, and you are choosing between reading every incoming ticket yourself or letting an app surface the likely matches for you.
That is what we built Merge Assistant to do. It scores potential duplicates on the ticket itself, using a per project corpus so it learns your vocabulary, extends the scan across the projects you allow, and forwards comments and attachments onto the surviving issue when you confirm. On a Service Management project it posts a public note on the closed request so the reporter knows where to continue.
One deliberate limitation: it never merges on its own. Detection is automatic, the decision stays with a human, because an irreversible merge on a false positive costs far more than the seconds it saves.