Preventing Storage Exhaustion in Harbor with Project Quotas (v2.x)
Learn how to use Harbor Project Quotas to prevent a single team or pipeline from exhausting your registry's storage, with concrete UI and API examples, and understand the Garbage Collection gap that delays quota recovery.
07 Nov 2026, 14:45 UTC

The Danger of the Uncapped Registry
In a multi-tenant Harbor deployment, a single runaway CI/CD pipeline can crash the entire container registry. Whether it's a developer pushing debug images every few minutes or an automated build that fails to prune old tags, uncontrolled artifact proliferation leads to storage exhaustion. When the underlying storage backend—be it S3, Azure Blob, or a local filesystem—hits 100%, the registry stops functioning for everyone, not just the offending team.
The solution is to shift from global storage management to Project Quotas. By enforcing limits at the project level, you isolate resource consumption and ensure that one team's inefficiency doesn't become a production outage for the rest of the organization. This feature has been stable since Harbor v2.0, though specific API fields and UI paths may vary slightly between minor releases.
Hard vs. Soft Limits: Choosing Your Enforcement
Harbor allows you to define quotas based on two metrics: the total number of artifacts (images and Helm charts) and the total storage size consumed. Each metric can be configured with two enforcement modes:
- Hard Limits: Strict boundaries. Once a project reaches its storage or artifact limit, Harbor rejects further
pushoperations. This is the only way to guarantee the physical storage backend is protected. - Soft Limits: Early warning systems. When a project exceeds a soft limit, Harbor triggers alerts (via email or webhook) but continues to allow pushes. Ideal for teams that need flexibility but require visibility into growth.
You can mix modes—for example, a soft limit at 8 GB to alert the team, and a hard limit at 10 GB to prevent overrun.
Implementing Quotas: UI and API
To implement quotas, navigate to Projects → [Project Name] → Quota in the Harbor UI (requires project admin role). For automation, use the Harbor API. The following example sets a 10 GB hard storage limit and a 500-artifact hard limit for project ID 3:
curl -X PUT -u "admin:password" \
-H "Content-Type: application/json" \
-d '{"quota": {"hard": {"storage_limit": 10737418240, "artifact_count_limit": 500}, "soft": {"storage_limit": 8589934592}}}' \
https://harbor.example.com/api/v2.0/projects/3/quotaStorage limits are expressed in bytes. The API returns 200 on success; a 400 indicates malformed payload, 404 if the project doesn't exist.
Worked Example: Verifying a 10 GB Hard Limit
Consider a "Development" project limited to 10 GB to prevent it from consuming the shared storage pool. To verify enforcement:
- Configure the Quota: In the Harbor UI, go to
Projects → Development → Quota. Set storage limit to 10 GB, select "Hard", and save. - Push Large Artifacts: From a client machine with push permissions, upload images that approach the limit. For example, push three 4 GB images:
docker tag large-base:latest harbor.example.com/development/large-app:v1
docker push harbor.example.com/development/large-app:v1
# Repeat for v2, v3- Observe the Failure: Once the 10 GB threshold is crossed, the next push attempt fails. Harbor typically returns a
403 Forbiddenwith a JSON body indicating quota exceeded, though some versions may return500 Internal Server Errorif the quota check encounters an internal issue. Check the registry logs for the exact error code in your version.
# Example failure output (your version may vary)
docker push harbor.example.com/development/large-app:v4
# Error response from daemon: received unexpected HTTP status: 403 Forbidden
# {"errors":[{"code":"QUOTA_EXCEEDED","message":"project quota exceeded"}]}The Garbage Collection Gap
A critical detail: deleting an image does not immediately reclaim quota space. Harbor uses content-addressable storage where layers are shared across images. Deleting a tag or manifest removes the reference, but the actual blobs remain on disk until Garbage Collection (GC) runs.
GC is a system-wide operation that must be triggered by a Harbor system administrator—it cannot be run per-project. The GC process scans the entire registry, identifies orphaned blobs no longer referenced by any manifest across all projects, and deletes them from the backend storage. Only after GC completes does the project's quota usage update.
Diagnostic Decision: Why Is My Quota Still Full?
| Symptom | Probable Cause | Required Action |
|---|---|---|
| Deleted images, but push still fails with quota error | Blobs still exist in storage; GC has not run | Request system admin to run Garbage Collection |
| Project quota shows available space, but pushes fail | Global storage backend (S3, disk) is full | Check underlying storage capacity; expand or clean globally |
| Push fails immediately on first upload to new project | Quota set too low for base image layers | Increase project storage limit |
Choosing Appropriate Limits
There's no universal formula, but a practical starting point:
- Development projects: Set hard limit at 2–3× the average monthly artifact size. Use soft limit at 70% of hard.
- Production projects: Set hard limit based on approved image count × max image size + 20% headroom. Avoid soft limits; use monitoring alerts instead.
- Shared/base image projects: Set higher limits; these layers are deduplicated across projects, so actual storage impact is lower than the sum of project quotas.
Monitor actual usage for 2–4 weeks before hardening limits. Harbor's quota dashboard (Projects → [Project] → Quota) shows current consumption vs. limits.
Trade-offs and Limitations
Project quotas provide essential isolation but introduce CI/CD stability risk. If a hard limit is reached during a critical deployment, the pipeline fails. Mitigate by:
- Combining hard limits with monitoring alerts (Prometheus metrics:
harbor_project_quota_usage_bytes,harbor_project_quota_limit_bytes). - Scheduling GC frequently (daily or after major cleanup) in high-velocity environments to reduce the lag between deletion and quota recovery.
- Avoiding hard limits on production-critical projects unless you have automated quota-increase workflows.
Additionally, the asynchronous nature of GC means there's a lag between data deletion and quota availability. In high-velocity environments, this can cause "false positive" quota errors if GC isn't scheduled frequently enough.
Verification and Recovery
To verify quotas function correctly, push a series of images that incrementally approach the limit and confirm the exact point of failure. Monitor the Project → Quota dashboard in Harbor for real-time usage.
Recovery: If a hard quota causes an unexpected outage, a project admin can immediately restore service by increasing the limit or disabling the quota in the UI or via API. This change takes effect on the next API call. Note: disabling quota removes the safeguard; prefer increasing the limit first.
Note: This article reflects Harbor v2.x behavior. Specific error codes, API paths, and GC scheduling options may vary by minor version. Verify against your deployed version before implementing in production.