Quota Management Guide
Overview
The SCORM API implements quota management to control resource usage per tenant. Quotas limit the number of packages and total storage space each tenant can use.
Quota Types
Package Quota
Limits the total number of SCORM packages a tenant can upload:
- Default: 100 packages (configurable)
- Enforcement: Checked before package upload
- Error:
QUOTA_EXCEEDEDif limit reached
Storage Quota
Limits the total storage space (in bytes) a tenant can use:
- Default: 50 GB (configurable)
- Enforcement: Checked before package upload
- Error:
QUOTA_EXCEEDEDif limit reached
Default Quotas
Default quotas are set via environment variables:
SCORM_DEFAULT_MAX_PACKAGES=100
SCORM_DEFAULT_MAX_STORAGE_GB=50
Tenant-Specific Quotas
Quotas can be customized per tenant in the tenant_limits table:
CREATE TABLE tenant_limits (
tenant_id UUID PRIMARY KEY REFERENCES scorm_tenants(id),
max_packages INTEGER,
max_storage_bytes BIGINT,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
Setting Tenant Quotas
Via Database:
INSERT INTO tenant_limits (tenant_id, max_packages, max_storage_bytes)
VALUES (
'550e8400-e29b-41d4-a716-446655440000',
500, -- 500 packages
107374182400 -- 100 GB (100 * 1024 * 1024 * 1024)
)
ON CONFLICT (tenant_id)
DO UPDATE SET
max_packages = EXCLUDED.max_packages,
max_storage_bytes = EXCLUDED.max_storage_bytes,
updated_at = NOW();
Via Admin API (if implemented):
curl -X PATCH https://api.scorm.com/api/admin/tenants/{tenantId}/limits \
-H "Authorization: Bearer admin-token" \
-H "Content-Type: application/json" \
-d '{
"max_packages": 500,
"max_storage_bytes": 107374182400
}'
Checking Quota Status
Get Current Usage
curl https://api.scorm.com/api/v1/quotas \
-H "X-API-Key: your-key"
Response:
{
"package_quota": {
"limit": 100,
"used": 45,
"remaining": 55,
"usage_percentage": 45
},
"storage_quota": {
"limit_bytes": 53687091200,
"used_bytes": 24159191040,
"remaining_bytes": 29527900160,
"usage_percentage": 45,
"limit_gb": 50,
"used_gb": 22.5,
"remaining_gb": 27.5
}
}
Programmatic Check
interface QuotaStatus {
package_quota: {
limit: number;
used: number;
remaining: number;
usage_percentage: number;
};
storage_quota: {
limit_bytes: number;
used_bytes: number;
remaining_bytes: number;
usage_percentage: number;
limit_gb: number;
used_gb: number;
remaining_gb: number;
};
}
async function checkQuotaStatus(apiKey: string): Promise<QuotaStatus> {
const response = await fetch('https://api.scorm.com/api/v1/quotas', {
headers: { 'X-API-Key': apiKey }
});
return response.json();
}
Quota Enforcement
Package Upload
Before uploading a package, the system checks:
- Package Count: Current package count <
max_packages - Storage Space: Current storage + new package size <
max_storage_bytes
Error Response:
{
"error": {
"code": "QUOTA_EXCEEDED",
"message": "Storage quota exceeded. Used: 50 GB / Limit: 50 GB",
"details": {
"quota_type": "storage",
"limit": 53687091200,
"used": 53687091200,
"required": 1048576000,
"available": 0
}
}
}
Quota Calculation
Package Count:
- Counts all packages for the tenant (including versions)
- Soft-deleted packages are excluded
Storage Usage:
- Sum of
file_size_bytesfor all packages - Includes all package versions
- Excludes soft-deleted packages
Quota Warnings
Usage Thresholds
The system provides warnings at usage thresholds:
- 75%: Warning level (yellow)
- 90%: Critical level (orange)
- 100%: Quota exceeded (red)
Monitoring Quota Usage
async function monitorQuota(apiKey: string) {
const status = await checkQuotaStatus(apiKey);
const packageWarning = status.package_quota.usage_percentage >= 75;
const storageWarning = status.storage_quota.usage_percentage >= 75;
if (packageWarning || storageWarning) {
console.warn('Quota usage high:', {
packages: `${status.package_quota.used}/${status.package_quota.limit}`,
storage: `${status.storage_quota.used_gb.toFixed(2)}/${status.storage_quota.limit_gb} GB`
});
}
return status;
}
Managing Quotas
Increasing Quotas
For Development:
- Update
tenant_limitstable directly - Or contact support with tenant ID
For Production:
- Submit quota increase request
- Provide business justification
- Review usage patterns
- Approve and update quotas
Reducing Quotas
To reduce quota usage:
- Delete Unused Packages: Remove packages no longer needed
- Archive Old Packages: Move to cold storage (if available)
- Optimize Package Sizes: Compress assets, remove unused files
- Clean Up Versions: Remove old package versions
Package Deletion
# Delete a package (releases storage)
curl -X DELETE https://api.scorm.com/api/v1/packages/{packageId} \
-H "X-API-Key: your-key"
Note: Deleting a package immediately releases its storage quota.
Quota Best Practices
1. Monitor Regularly
Check quota status regularly to avoid unexpected limits:
// Check quotas daily
setInterval(async () => {
const status = await checkQuotaStatus(apiKey);
if (status.package_quota.usage_percentage > 80) {
alert('Package quota approaching limit');
}
}, 24 * 60 * 60 * 1000); // Daily
2. Plan for Growth
Estimate future needs and request quota increases proactively:
- Package Growth: Estimate packages per month
- Storage Growth: Estimate average package size × growth rate
- Buffer: Request 20-30% more than current needs
3. Optimize Storage
- Compress Assets: Use optimized images, videos
- Remove Unused Content: Delete test packages
- Version Management: Keep only necessary versions
4. Implement Cleanup
Automate cleanup of old or unused packages:
async function cleanupOldPackages(apiKey: string, olderThanDays: number) {
const cutoffDate = new Date();
cutoffDate.setDate(cutoffDate.getDate() - olderThanDays);
const packages = await listPackages(apiKey);
const oldPackages = packages.filter(p =>
new Date(p.created_at) < cutoffDate
);
for (const pkg of oldPackages) {
await deletePackage(apiKey, pkg.id);
console.log(`Deleted package: ${pkg.id}`);
}
}
Quota Errors
Common Error Codes
QUOTA_EXCEEDED: Quota limit reachedQUOTA_CHECK_FAILED: Error checking quota statusINVALID_QUOTA_CONFIG: Invalid quota configuration
Error Handling
async function uploadPackageWithQuotaCheck(file: File, apiKey: string) {
// Check quota before upload
const quota = await checkQuotaStatus(apiKey);
if (quota.storage_quota.remaining_bytes < file.size) {
throw new Error(
`Insufficient storage. Required: ${file.size} bytes, ` +
`Available: ${quota.storage_quota.remaining_bytes} bytes`
);
}
if (quota.package_quota.remaining < 1) {
throw new Error('Package quota exceeded');
}
// Proceed with upload
return uploadPackage(file, apiKey);
}
Quota Reporting
Usage Reports
Generate quota usage reports:
interface QuotaReport {
tenant_id: string;
period: {
start: string;
end: string;
};
package_quota: {
limit: number;
used: number;
peak_usage: number;
average_usage: number;
};
storage_quota: {
limit_bytes: number;
used_bytes: number;
peak_bytes: number;
average_bytes: number;
};
trends: {
package_growth_rate: number; // packages per month
storage_growth_rate: number; // bytes per month
};
}
Troubleshooting
Issue: Quota Not Updating After Deletion
Causes:
- Soft deletion (package marked deleted but not removed)
- Cached quota values
- Database replication lag
Solutions:
- Wait a few seconds and check again
- Hard delete packages if soft delete is enabled
- Clear cache if applicable
Issue: Quota Check Fails
Causes:
- Database connection issues
- Missing tenant_limits record
- Invalid quota configuration
Solutions:
- Check database connectivity
- Verify tenant_limits table exists
- Review quota configuration
Issue: Incorrect Quota Calculation
Causes:
- Orphaned package records
- Inconsistent storage calculations
- Version counting issues
Solutions:
- Run quota recalculation script
- Audit package records
- Verify storage calculations
Last Updated: 2025-01-12
Version: 1.0
For package management, see Package Management Guide.