ARTIFACTORY: How to Identify and Clean Up Unused Artifacts to Optimize Storage in JFrog Artifactory

AuthorFullName__c
Pratham D Hegde
articleNumber
000007103
FirstPublishedDate
2026-08-05T06:59:23Z
lastModifiedDate
2026-08-05

ARTIFACTORY: How to Identify and Clean Up Unused Artifacts to Optimize Storage in JFrog Artifactory

Overview
This article helps you find and remove unused or duplicate artifacts in JFrog Artifactory to reduce storage costs. It uses two methods GraphQL and AQL along with safe deletion steps.


Why Storage Grows Unexpectedly
  • Same artifact stored across multiple repositories
  • Storing large, unused artifacts that are no longer needed
  • Deleting an artifact does not always free space 1:1 due to deduplication


Step 1 — Find Duplicate Packages (GraphQL)
Use this to see which packages exist in more than one repo, their size, and download count.
curl --location 'https://<your-instance>.jfrog.io/metadata/api/v1/query' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <your_token>' \
--data '{
  "query": "query { packages(filter: {name: \"*busybox*\", packageTypeIn: [DOCKER OCI]}) { edges {
node { name versions { name size created modified repos { name type leadFilePath } stats {
downloadCount } } } } } }"
}' | jq .
e.g., output:
{
 "data": {
  "packages": {
   "edges": [
    {
     "node": {
      "name": "library/busybox",
      "versions": [
       {
        "name": "sha256__d82f458899c9696cb26a7c02d5568f81c8c8223f8661bb2a7988b269c8b9051e",
        "size": "9535",
        "created": "2025-10-08T02:44:17.591Z",
        "modified": "2025-10-08T02:42:52.477Z",
        "repos": [
         {
          "name": "devops-docker-remote-cache",
          "type": "remote",
          "leadFilePath": "library/busybox/latest/list.manifest.json"
         }
        ],
        "stats": {
         "downloadCount": 0
        }
       },
       {
        "name": "sha256__cddc8af5547af9de5e6fb66b36d66ef7418561204e1255ae528d0b2c919d09a3",
        "size": "1903853",
        "created": "2025-09-25T09:20:18.969Z",
        "modified": "2025-09-09T09:01:22Z",
        "repos": [
         {
          "name": "pratham-adoption-docker-remote-cache",
          "type": "remote",
          "leadFilePath":
"library/busybox/sha256__cddc8af5547af9de5e6fb66b36d66ef7418561204e1255ae528d0b2c919d09a3/manifest.json"
         }
        ],
        "stats": {
         "downloadCount": 0
        }
       }
      ]
     }
    },
    {
     "node": {
      "name": "busybox",
      "versions": [
       {
        "name": "sha256__ab33eacc8251e3807b85bb6dba570e4698c3998eca6f0fc2ccb60575a563ea74",
        "size": "9534",
        "created": "2025-09-09T09:03:14.52Z",
        "modified": "2025-09-09T09:01:15Z",
        "repos": [
         {
          "name": "pratham-adoption-docker-remote-cache",
          "type": "remote",
          "leadFilePath": "busybox/latest/list.manifest.json"
         }
        ],
        "stats": {
         "downloadCount": 0
        }
       },
       {
        "name": "sha256__cddc8af5547af9de5e6fb66b36d66ef7418561204e1255ae528d0b2c919d09a3",
        "size": "1903853",
        "created": "2025-09-09T09:01:35.181Z",
        "modified": "2025-09-09T09:01:22Z",
        "repos": [
         {
          "name": "pratham-adoption-docker-remote-cache",
          "type": "remote",
          "leadFilePath":
"busybox/sha256__cddc8af5547af9de5e6fb66b36d66ef7418561204e1255ae528d0b2c919d09a3/manifest.json"
         }
        ],
        "stats": {
         "downloadCount": 0
        }
       },
       {
        "name": "latest",
        "size": "1903770",
        "created": "2026-02-19T06:57:01.439Z",
        "modified": "2026-02-19T06:56:49.494Z",
        "repos": [
         {
          "name": "pratham-docker-repo1",
          "type": "local",
          "leadFilePath": "busybox/latest/manifest.json"
         },
         {
          "name": "pratham-docker-repo3",
          "type": "local",
          "leadFilePath": "busybox/latest/manifest.json"
         }
        ],
        "stats": {
         "downloadCount": 6
        }
       }
      ]
     }
    }
   ]
  }
 }
}
What to look for:
  • Same package SHA appearing in multiple repos → duplicate
  • downloadCount: 0 → never used, safe candidate for removal


Step 2 — Find Unused Artifacts (AQL)
Find artifacts not downloaded within a set time window.
items.find({
  "repo": {"$match": "your-repo-name"},
  "stat.downloaded": {"$before": "90d"}
}).include("name", "repo", "path", "size", "stat.downloaded")
Adjust 90d to match your retention policy (e.g. 30d, 60d).


Step 3 - Protect Critical Artifacts Before Deleting
  • Promote to an Immutable Repository — artifacts cannot be deleted or overwritten
  • Use Before-Delete Workers — scripts that block deletion of artifacts matching your rules (e.g. tagged as stable or production)
Always review AQL results before deleting anything.


Step 4 — Delete Identified Artifacts (REST API)
curl -X DELETE \
  -H "Authorization: Bearer <your_token>" \
  "https://<your-instance>.jfrog.io/artifactory/<repo-name>/<path-to-artifact>"
  • Test on one artifact first before bulk deletion
  • After deletion, allow time before measuring storage savings (deduplication recalculates)


Related Documents