Chapter 12. Red Hat Quay quota management and enforcement overview
With Red Hat Quay quota management, superusers can track storage consumption and set soft or hard limits for organizations, repositories, or the entire registry.
Red Hat Quay superusers can manage capacity limits in the following ways:
- Quota reporting: An administrator can track the storage consumption of all organizations. Users can track the storage consumption of their assigned organization.
- Quota management: An administrator can define soft and hard checks for Red Hat Quay users. Soft checks tell users if the storage consumption of an organization reaches their configured threshold. Hard checks prevent users from pushing to the registry when storage consumption reaches the configured limit.
These features help service owners of a Red Hat Quay registry define service level agreements and support a healthy resource budget.
12.1. Quota management architecture Copy linkLink copied to clipboard!
Red Hat Quay quota management sums blob sizes at the repository and namespace level without double-counting shared blobs. You can enforce storage limits and reject pushes when quotas are exceeded.
Because manifest list totals are counted toward the repository total, the total quota consumed when upgrading from a previous version of Red Hat Quay might be reportedly differently in Red Hat Quay 3.9. In some cases, the new total might go over a repository’s previously-set limit. Red Hat Quay administrators might have to adjust the allotted quota of a repository to account for these changes.
The quota management feature works by calculating the size of existing repositories and namespace with a backfill worker, and then adding or subtracting from the total for every image that is pushed or garbage collected afterwords. Additionally, the subtraction from the total happens when the manifest is garbage collected.
Because subtraction occurs from the total when the manifest is garbage collected, there is a delay in the size calculation until it is able to be garbage collected.
The following database tables hold the quota repository size, quota namespace size, and quota registry size, in bytes, of a Red Hat Quay repository within an organization:
-
QuotaRepositorySize -
QuotaNameSpaceSize -
QuotaRegistrySize
The organization size is calculated by the backfill worker to ensure that it is not duplicated. When an image push is initialized, the user’s organization storage is validated to check if it is beyond the configured quota limits. If an image push exceeds defined quota limitations, a soft or hard check occurs:
- For a soft check, users are notified.
- For a hard check, the push is stopped.
If storage consumption is within configured quota limits, the push is allowed to proceed.
Image manifest deletion follows a similar flow, whereby the links between associated image tags and the manifest are deleted. Additionally, after the image manifest is deleted, the repository size is recalculated and updated in the QuotaRepositorySize, QuotaNameSpaceSize, and QuotaRegistrySize tables.
12.2. Quota management limitations Copy linkLink copied to clipboard!
Quota management in Red Hat Quay has limits related to push-time calculation and database-backed maximum sizes. Review these constraints before you set organization quotas.
One limitation of the quota management feature is that calculating resource consumption on the push of an artifact results in the calculation becoming part of the push’s critical path. Without this, usage data might drift.
The maximum storage quota size depends on the selected database:
| Database | Maximum quota size |
|---|---|
| Postgres | 8388608 TB |
| MySQL | 8388608 TB |
| SQL Server | 16777216 TB |
12.3. Quota management configuration fields Copy linkLink copied to clipboard!
The following configuration fields enable and customize quota management functionality in Red Hat Quay. Quota management helps administrators enforce storage usage policies at the organization level by allowing them to set usage limits, calculate blob sizes, and control tag deletion behavior.
| Field | Type | Description |
|---|---|---|
| FEATURE_QUOTA_MANAGEMENT | Boolean | Enables configuration, caching, and validation for quota management feature.
Default: |
| FEATURE_QUOTA_NOTIFICATIONS | Boolean | Enables external notification channels, such as email, for quota threshold alerts. When enabled, namespace owners receive proactive notifications when storage consumption crosses configured warning or critical thresholds.
Default: |
| FEATURE_MAILING | Boolean |
Enables email delivery features across Red Hat Quay. Must be
Default: |
| QUOTA_NOTIFICATION_COOLDOWN_SECONDS | Integer |
Cooldown period in seconds before re-sending a quota notification for the same threshold (default: 86400 / 24 hours). The system prevents repeated notifications for the same namespace and threshold combination within this window. If storage usage drops below a threshold and later crosses the threshold again, the notification state is cleared and the notification will re-fire upon the new crossing. Notification claims (
Default: |
| QUOTA_NOTIFICATION_WORKER_POLL_PERIOD | Integer |
How often, in seconds, the quota notification background worker polls for threshold crossings that occur between image pushes—for example, when an administrator lowers a quota limit. Default:
Default: |
| DEFAULT_SYSTEM_REJECT_QUOTA_BYTES | String | Enables system default quota reject byte allowance for all organizations. By default, no limit is set. |
| QUOTA_BACKFILL | Boolean | Enables the quota backfill worker to calculate the size of pre-existing blobs.
Default: |
| QUOTA_TOTAL_DELAY_SECONDS | String | The time delay for starting the quota backfill. Rolling deployments can cause incorrect totals. This field must be set to a time longer than it takes for the rolling deployment to complete.
Default: |
| PERMANENTLY_DELETE_TAGS | Boolean | Enables functionality related to the removal of tags from the time machine window.
Default: |
| RESET_CHILD_MANIFEST_EXPIRATION | Boolean |
Resets the expirations of temporary tags targeting the child manifests. With this feature set to
Default: |
Quota management example YAML
# ...
FEATURE_QUOTA_MANAGEMENT: true
FEATURE_QUOTA_NOTIFICATIONS: true
DEFAULT_SYSTEM_REJECT_QUOTA_BYTES: "100gb"
QUOTA_BACKFILL: true
QUOTA_TOTAL_DELAY_SECONDS: 3600
QUOTA_NOTIFICATION_COOLDOWN_SECONDS: 86400
QUOTA_NOTIFICATION_WORKER_POLL_PERIOD: 300
PERMANENTLY_DELETE_TAGS: true
RESET_CHILD_MANIFEST_EXPIRATION: true
# ...
12.4. Managing quota limits by using the API Copy linkLink copied to clipboard!
You can use the Red Hat Quay API to check, create, change, or delete organization quota limits when an organization does not yet have a quota configured.
Before you begin, you must have generated an OAuth access token.
12.4.1. Setting quota by using the API Copy linkLink copied to clipboard!
To create, view, or update an organization storage quota in Red Hat Quay, you can call the organization quota API endpoints with an OAuth access token.
Procedure
To set a quota for an organization, you can use the
POST /api/v1/organization/{orgname}/quotaendpoint:$ curl -X POST "https://<quay-server.example.com>/api/v1/organization/<orgname>/quota" \ -H "Authorization: Bearer <access_token>" \ -H "Content-Type: application/json" \ -d '{ "limit_bytes": 10737418240, "limits": "10 Gi" }'Example output:
"Created"Use the
GET /api/v1/organization/{orgname}/quotacommand to see if your organization already has an established quota:$ curl -k -X GET -H "Authorization: Bearer <token>" -H 'Content-Type: application/json' https://<quay-server.example.com>/api/v1/organization/<organization_name>/quota | jqExample output:
[{"id": 1, "limit_bytes": 10737418240, "limit": "10.0 GiB", "default_config": false, "limits": [], "default_config_exists": false}]You can use the
PUT /api/v1/organization/{orgname}/quota/{quota_id}command to modify the existing quota limitation. For example:$ curl -X PUT "https://<quay-server.example.com>/api/v1/organization/<orgname>/quota/<quota_id>" \ -H "Authorization: Bearer <access_token>" \ -H "Content-Type: application/json" \ -d '{ "limit_bytes": <limit_in_bytes> }'Example output:
{"id": 1, "limit_bytes": 21474836480, "limit": "20.0 GiB", "default_config": false, "limits": [], "default_config_exists": false}
12.4.2. Viewing quota usage by using the API Copy linkLink copied to clipboard!
To view organization and repository storage consumption in Red Hat Quay, you can query the repository list and organization API endpoints.
Procedure
To view storage consumed by repositories in an organization, send a
GETrequest to the/api/v1/repositoryendpoint:$ curl -k -X GET -H "Authorization: Bearer <token>" -H 'Content-Type: application/json' 'https://<quay-server.example.com>/api/v1/repository?last_modified=true&namespace=<organization_name>&popularity=true&public=true' | jqExample output:
{ "repositories": [ { "namespace": "testorg", "name": "ubuntu", "description": null, "is_public": false, "kind": "image", "state": "NORMAL", "quota_report": { "quota_bytes": 27959066, "configured_quota": 104857600 }, "last_modified": 1651225630, "popularity": 0, "is_starred": false } ] }To view the quota report for multiple repositories in the organization, send a
GETrequest to the/api/v1/repositoryendpoint:$ curl -k -X GET -H "Authorization: Bearer <token>" -H 'Content-Type: application/json' 'https://<quay-server.example.com>/api/v1/repository?last_modified=true&namespace=<organization_name>&popularity=true&public=true'Example output:
{ "repositories": [ { "namespace": "testorg", "name": "ubuntu", "description": null, "is_public": false, "kind": "image", "state": "NORMAL", "quota_report": { "quota_bytes": 27959066, "configured_quota": 104857600 }, "last_modified": 1651225630, "popularity": 0, "is_starred": false }, { "namespace": "testorg", "name": "nginx", "description": null, "is_public": false, "kind": "image", "state": "NORMAL", "quota_report": { "quota_bytes": 59231659, "configured_quota": 104857600 }, "last_modified": 1651229507, "popularity": 0, "is_starred": false } ] }To view quota information in the organization details, send a
GETrequest to the/api/v1/organization/<organization_name>endpoint:$ curl -k -X GET -H "Authorization: Bearer <token>" -H 'Content-Type: application/json' 'https://<quay-server.example.com>/api/v1/organization/<organization_name>' | jqExample output:
{ "name": "testorg", ... "quotas": [ { "id": 1, "limit_bytes": 104857600, "limits": [] } ], "quota_report": { "quota_bytes": 87190725, "configured_quota": 104857600 } }
12.4.3. Setting reject and warning limits by using the API Copy linkLink copied to clipboard!
To configure reject and warning thresholds for an organization quota in Red Hat Quay, you can post limit definitions to the organization quota limit API endpoint.
Procedure
To set a reject limit, send a
POSTrequest to the/api/v1/organization/<organization_name>/quota/<quota_id>/limitendpoint. For example:$ curl -k -X POST -H "Authorization: Bearer <token>" -H 'Content-Type: application/json' -d '{"type":"Reject","threshold_percent":80}' https://<quay-server.example.com>/api/v1/organization/<organization_name>/quota/1/limitTo set a warning limit, send a
POSTrequest to the same endpoint. For example:$ curl -k -X POST -H "Authorization: Bearer <token>" -H 'Content-Type: application/json' -d '{"type":"Warning","threshold_percent":50}' https://<quay-server.example.com>/api/v1/organization/<organization_name>/quota/1/limit
12.4.4. Viewing reject and warning limits by using the API Copy linkLink copied to clipboard!
To view reject and warning thresholds configured for an organization quota in Red Hat Quay, you can send a GET request to the organization quota API endpoint.
Procedure
View the reject and warning limits by using the
/api/v1/organization/<organization_name>/quotaendpoint. For example:$ curl -k -X GET -H "Authorization: Bearer <token>" -H 'Content-Type: application/json' https://<quay-server.example.com>/api/v1/organization/<organization_name>/quota | jqExample output:
[ { "id": 1, "limit_bytes": 104857600, "default_config": false, "limits": [ { "id": 2, "type": "Warning", "limit_percent": 50 }, { "id": 1, "type": "Reject", "limit_percent": 80 } ], "default_config_exists": false } ]