Skip to content

quota_usage.used counter drifts from actual storage #23655

Description

@nikitakodkany

Problem

GET /projects/{name}/summary returns quota_usage.used which is maintained as a running counter in the database rather than computed from actual blob storage. This counter can drift from reality when:

  • An upload fails mid-way
  • A transaction rollback does not fully complete

The counter only self-corrects when garbage collection (GC) or an explicit delete operation runs. During the drift window, quota checks are inaccurate.

Current behavior

quota_usage.used is a mutable running counter. It increments/decrements on blob operations but has no reconciliation path for failed or partially rolled back transactions.

Expected behavior

Quota usage reflects actual bytes stored in project_blob at all times, with no drift.

Proposed fix

Harbor already has CalculateTotalSizeByProject internally, which does a live SUM from project_blob. Rather than adding a new endpoint as a workaround, the quota check path should be reworked to eliminate the running counter entirely either by:

  1. Live aggregate: Replace quota_usage.used reads with a query against project_blob backed by an appropriate index.
  2. Update an indexed aggregate transactionally on every blob insert/delete, eliminating async drift.

Either approach removes the need for GC to act as a correctness mechanism for quota.

Notes

  • CalculateTotalSizeByProject exists in the codebase but is not currently exposed via any public API. A GET /projects/{name}/storage endpoint was considered as a short-term workaround but a proper fix to the counter is preferred
  • This was discussed in the Harbor community Slack - https://cloud-native.slack.com/archives/CC1E09J6S/p1783454715724819

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions