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_EXCEEDED if 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_EXCEEDED if 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:

  1. Package Count: Current package count < max_packages
  2. 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_bytes for 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:

  1. Update tenant_limits table directly
  2. Or contact support with tenant ID

For Production:

  1. Submit quota increase request
  2. Provide business justification
  3. Review usage patterns
  4. Approve and update quotas

Reducing Quotas

To reduce quota usage:

  1. Delete Unused Packages: Remove packages no longer needed
  2. Archive Old Packages: Move to cold storage (if available)
  3. Optimize Package Sizes: Compress assets, remove unused files
  4. 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 reached
  • QUOTA_CHECK_FAILED: Error checking quota status
  • INVALID_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.