Find Your Jira’s Hidden Custom Field Waste

Find Your Jira’s Hidden Custom Field Waste

Find Your Jira’s Hidden Custom Field Waste

4 SQL queries that expose unused, duplicate, and abandoned fields

In Part 1, you counted your custom fields and checked for performance symptoms. Now it’s time to identify exactly which Jira custom fields are dragging your instance down. Not all custom fields are equal. Some are critical to your workflows. Others haven’t been touched since 2019. The goal of this article is to separate the essential from the expendable — with data, not guesswork.
!

Before You Start: The Exclusion Rule

One critical caveat before running any queries: some “empty” fields aren’t actually empty.

Jira Service Management, Jira Software (the agile features), Capture, and Portfolio for Jira store their custom field data in separate datastores — not in the standard customfieldvalue table. If you query that table, these fields will appear unused even when they’re actively in use.

Every query below excludes these field types:

AND cf.CUSTOMFIELDTYPEKEY NOT LIKE '%com.atlassian.servicedesk%'
AND cf.CUSTOMFIELDTYPEKEY NOT LIKE '%com.pyxis.greenhopper%'
AND cf.CUSTOMFIELDTYPEKEY NOT LIKE '%com.atlassian.bonfire%'
AND cf.CUSTOMFIELDTYPEKEY NOT LIKE '%com.atlassian.jpo%'
DON’T SKIP THESE EXCLUSIONS

You don’t want to delete your Sprint field because a query said it was “unused.”

1

Completely Unused Fields LOW RISK

These fields exist in your system but have never contained data. Zero values. Ever.

SELECT cf.id, cf.cfname, cf.description, cf.CUSTOMFIELDTYPEKEY
FROM customfield cf
LEFT JOIN customfieldvalue cfv ON cf.id = cfv.customfield
WHERE cfv.id IS NULL
AND cf.CUSTOMFIELDTYPEKEY NOT LIKE '%com.atlassian.servicedesk%'
AND cf.CUSTOMFIELDTYPEKEY NOT LIKE '%com.pyxis.greenhopper%'
AND cf.CUSTOMFIELDTYPEKEY NOT LIKE '%com.atlassian.bonfire%'
AND cf.CUSTOMFIELDTYPEKEY NOT LIKE '%com.atlassian.jpo%'
ORDER BY cf.cfname;

What you’ll find:

  • Fields created “just in case” that were never used
  • Fields from plugins that were uninstalled
  • Duplicate fields created by mistake and then abandoned
  • Test fields someone forgot to delete
RISK ASSESSMENT

If a field has never held data, deleting it won’t cause data loss. But still check if it’s referenced in screens, workflows, or automation rules before removal.

Typical results: In a mature Jira instance (5+ years), expect 10-30% of custom fields to return in this query.
2

Low-Usage Fields MEDIUM RISK

These fields have data, but barely. Maybe 5 issues out of 100,000.

SELECT COUNT(*) as usage_count, cf.id, cf.cfname, cf.CUSTOMFIELDTYPEKEY
FROM customfield cf
LEFT JOIN customfieldvalue cfv ON cf.id = cfv.customfield
WHERE cf.CUSTOMFIELDTYPEKEY NOT LIKE '%com.atlassian.servicedesk%'
AND cf.CUSTOMFIELDTYPEKEY NOT LIKE '%com.pyxis.greenhopper%'
AND cf.CUSTOMFIELDTYPEKEY NOT LIKE '%com.atlassian.bonfire%'
AND cf.CUSTOMFIELDTYPEKEY NOT LIKE '%com.atlassian.jpo%'
AND cfv.id IS NOT NULL
GROUP BY cf.id, cf.cfname, cf.CUSTOMFIELDTYPEKEY
HAVING COUNT(*) < 50
ORDER BY usage_count ASC;

Adjusting the threshold:

The < 50 threshold is a starting point. Scale it to your instance:

Total Issues Suggested Threshold Logic
10,000 < 10 0.1% of issues
100,000 < 100 0.1% of issues
500,000 < 500 0.1% of issues

The 0.1% rule comes from The Jira Guy's recommendation: if fewer than one-tenth of one percent of issues use a field, it's worth questioning whether that field should exist globally.

What you'll find:

  • Project-specific fields that got global context by mistake
  • Fields from completed/archived projects
  • Experimental fields that didn't get adoption
  • Fields replaced by newer alternatives but never cleaned up
RISK ASSESSMENT

There's data here, so you need to decide: migrate it, archive it, or accept losing it.

3

Duplicate Field Names HIGH RISK

The classic "which Priority field is the real one?" problem.

SELECT cfname, COUNT(*) as duplicate_count
FROM customfield
GROUP BY cfname
HAVING COUNT(*) > 1
ORDER BY duplicate_count DESC;

What you'll find:

  • Fields created by different admins who didn't check existing fields
  • Test/production duplicates that both ended up in production
  • Fields with slightly different configurations (different options, different contexts) but same name
WHY THIS MATTERS

Duplicate names create chaos: Users select the wrong field on forms. JQL searches return unexpected results. Reports pull from inconsistent data sources. New admins can't tell which field to use.

Next step: For each duplicate, run this to see which projects actually use each variant:

SELECT DISTINCT p.pkey as project_key, cf.id, cf.cfname
FROM customfield cf
JOIN customfieldvalue cfv ON cf.id = cfv.customfield
JOIN jiraissue ji ON cfv.issue = ji.id
JOIN project p ON ji.project = p.id
WHERE cf.cfname = 'Your Duplicate Field Name'
ORDER BY p.pkey, cf.id;
RISK ASSESSMENT

HIGH for confusion, MEDIUM for deletion. You can't just delete one — you need to audit which projects use which field, potentially merge data, and update screens/workflows.

4

Abandoned Fields MEDIUM RISK

These fields exist, have historical data, but haven't been touched in a long time.

SELECT cf.id, cf.cfname
FROM customfield cf
WHERE cf.cfname NOT IN (
    SELECT item.field 
    FROM changeitem item
    JOIN changegroup cg ON item.groupid = cg.id
    WHERE item.fieldtype = 'custom' 
    AND cg.created > '2024-01-01'
)
AND cf.CUSTOMFIELDTYPEKEY NOT LIKE '%com.pyxis.greenhopper%'
AND cf.CUSTOMFIELDTYPEKEY NOT LIKE '%com.atlassian.servicedesk%'
AND cf.CUSTOMFIELDTYPEKEY NOT LIKE '%com.atlassian.bonfire%'
AND cf.CUSTOMFIELDTYPEKEY NOT LIKE '%com.atlassian.jpo%'
ORDER BY cf.cfname;

Adjust the date ('2024-01-01') to your preferred lookback period:

Lookback Period Approach
6 months Aggressive cleanup
12 months Balanced approach
24 months Conservative

What you'll find:

  • Fields from deprecated processes
  • Fields tied to completed long-term projects
  • Fields that teams stopped using but never formally retired
  • Historical tracking fields no longer relevant
RISK ASSESSMENT

The data exists but isn't being maintained. Question whether it still has business value before removal.

+

Bonus: Fields Created by Third-Party Plugins

Not all plugin fields are bad, but it's useful to know which plugins have left their mark:

SELECT cf.cfname, cf.CUSTOMFIELDTYPEKEY
FROM customfield cf
WHERE cf.CUSTOMFIELDTYPEKEY NOT LIKE '%com.atlassian%'
AND cf.CUSTOMFIELDTYPEKEY NOT LIKE '%com.pyxis%'
ORDER BY cf.CUSTOMFIELDTYPEKEY, cf.cfname;

What you'll find:

  • Fields from currently installed plugins (expected)
  • Fields from uninstalled plugins (cleanup candidates)
  • Fields from trial plugins you tested years ago

Cross-reference with your installed plugins list. Any field type from a plugin that's no longer installed is safe to investigate for deletion.

5

Running These Queries

Option A: Direct Database Access

If you have read-only database credentials:

psql -h your-db-host -U readonly_user -d jiradb -f audit_queries.sql
Option B: Database Browser Tool

Tools like Home Directory, Database & Log File Browser for Jira let you run these queries directly from Jira's admin interface:

  1. Navigate to the Database Browser
  2. Paste query
  3. Execute
  4. Export results to CSV

No SSH, no terminal, no database client installation.

Option C: Your DBA

If you don't have database access, send these queries to your DBA with an explanation. They'll appreciate that you came with specific, read-only queries rather than vague requests.

6

Organizing Your Results

After running all four queries, you should have:

Query Fields Found Risk Level
Unused [your count] Low
Low-usage [your count] Medium
Duplicates [your count] Medium-High
Abandoned [your count] Medium

Create a spreadsheet with columns:

  • Field ID
  • Field Name
  • Category (Unused/Low/Duplicate/Abandoned)
  • Plugin source (if applicable)
  • Decision (Delete/Keep/Investigate/Merge)
  • Notes

This becomes your cleanup roadmap.

⚠️ WHAT NOT TO DO YET

You now have a list of candidates. Do not mass-delete them.

Before removing any field, you need to verify:

  1. Is it used in any saved filters?
  2. Is it displayed on any dashboard gadgets?
  3. Is it referenced in workflow conditions, validators, or post-functions?
  4. Is it used in automation rules?
  5. Is it referenced in ScriptRunner scripts or behaviors?

A field can have zero data in customfieldvalue but still be actively referenced in your configuration. Deleting it will break things.

That verification process — and the safe deletion workflow — is exactly what we'll cover in Part 3.

The Bottom Line

You now have data-driven answers to the question "which custom fields should I clean up?"

Not hunches. Not "this looks old." Actual query results showing:

  • Fields with zero data (easiest wins)
  • Fields barely anyone uses (worth questioning)
  • Fields with duplicate names (causing confusion)
  • Fields nobody's touched in 12+ months (probably forgotten)

This is your hit list. Part 3 will show you how to safely execute on it.

This article is Part 2 of the "Custom Field Health Check" series for Jira Data Center administrators.

SQL queries validated for Jira Data Center 10+ on PostgreSQL. Original query patterns from The Jira Guy, updated and tested for current Jira versions based on Atlassian's schema documentation.

Scroll to Top