Skip to content

Configuration

Section 5 · From docs/RESILIENCE.md on GitHub

Everything sits under ratelimit in config.yaml (CloudGConfig.ratelimit, a RateLimitConfig). The section is additive: a config without it behaves exactly as the built-in defaults above. Unset (null) provider limits fall back to the built-ins; service overrides are merged into the built-in service table key by key.

A key that is not part of the models below, at any level of ratelimit (ratelimit, ratelimit.<provider>, ratelimit.<provider>.services.<name>), is ignored with a warning, and the rest of the config still loads:

WARNING cloudg.config: Unknown config key ratelimit.aws.max_rpss is ignored

5.1 ratelimit

Key Type Default Meaning
enabled bool true Master switch. false turns off pacing, breakers, cloudg-level retries and the Azure retry overrides for every provider. botocore keeps its own retries from aws.max_retries / aws.retry_mode, and coverage still labels throttling errors
aws, azure, gcp ProviderRateLimitConfig all defaults Per-provider settings (5.2)
live_cooldown_seconds float >= 0 120 Minimum time between two live collections of the same scope
live_max_concurrent int, 1 to 64 1 Live collections allowed at once per scope
live_max_concurrent_total int, 1 to 256 2 Live collections allowed at once overall
live_caller_max_operations int >= 0 0 New live collections per caller per window; 0 means unlimited
live_caller_window_seconds float > 0 3600 Length of that window
live_operation_timeout_seconds float > 0 or null 3600 A live collection running longer is cancelled and its scopes freed; null means no limit

5.2 ratelimit.<provider>

Key Type Default Meaning
enabled bool true Pace and circuit-break this provider. false makes its calls go straight to the SDK
max_rps float > 0 or null built-in (AWS 20, Azure 15, GCP 10) Default leaf rate per account x region x service
burst float > 0 or null built-in (AWS 40, Azure 100, GCP 20) Default leaf capacity
account_max_rps float > 0 or null built-in (Azure 20, others off) Aggregate rate per account, subscription or project
account_burst float > 0 or null built-in (Azure 200), else twice account_max_rps Capacity of the account bucket
global_max_rps float > 0 or null off Aggregate rate for every call to this provider in the process
global_burst float > 0 or null twice global_max_rps Capacity of the provider-wide bucket
max_concurrency int, 1 to 1024, or null built-in (AWS 128, others 16) Requests in flight per account (bulkhead, section 2.5)
adaptive bool true Halve a scope's rate on throttling and recover additively
min_rps float > 0 or null built-in (AWS 0.2, Azure 0.1, GCP 0.05) Floor of the adaptive rate
breaker_threshold int, 1 to 1000 5 Consecutive calls that failed on throttling or transient errors after their retries before the circuit opens
breaker_cooldown_seconds float >= 0 60 How long an open circuit rejects calls before a probe; doubles on each failed probe up to 600
max_retries int, 0 to 50 8 Retries of a throttled or transient call: azure-core retry_total / retry_status, consecutive api_core retries per GCP page, call_with_resilience. AWS SDK retries use aws.max_retries
max_backoff_seconds float > 0 60 Cap of one backoff sleep: azure-core retry_backoff_max, api_core Retry(maximum=), call_with_resilience
deadline_seconds float > 0 900 Overall time for one call including retries: azure-core RetryPolicy(timeout=), api_core Retry(timeout=), call_with_resilience
retry_budget int >= 0 500 Retries per provider, across every integration, before retrying stops; each success refunds 0.1
services map of name to ServiceRateLimitConfig {} Per-service or per-operation overrides (5.3)
live_cooldown_seconds float >= 0 or null null Overrides ratelimit.live_cooldown_seconds for live scopes of this provider

5.3 ratelimit.<provider>.services.<name>

The key is the SDK service name (AWS: ec2, iam, sts, s3, ...; Azure: network, compute, storage, resources, resourcegraph, ...; GCP: cloudasset) or <service>.<Operation> for one operation (ec2.DescribeImageAttribute, cloudasset.ListAssets). An operation key always gets its own bucket.

Key Type Default Meaning
max_rps float > 0, required Sustained requests per second
burst float > 0 or null twice max_rps Bucket capacity. An override replaces the whole built-in entry, so give the burst again if you want to keep it (the built-in ec2 burst of 100 becomes 20 if you set only max_rps: 10)
per_operation bool or null the built-in choice (true for AWS ec2) One bucket, and one circuit breaker, per API operation instead of one per service

5.4 Where each key takes effect

The four integrations are the AWS hooks (botocore event hooks on every boto3 and aioboto3 session cloudg builds), the Azure policy (the per-attempt pipeline policy plus the explicit RetryPolicy on every Azure SDK client, Resource Graph included), the GCP Cloud Asset Inventory listings, and call_with_resilience for your own code.

Key AWS hooks Azure policy GCP listings call_with_resilience
enabled, max_rps, burst, services (with per_operation) yes yes yes yes
account_max_rps, account_burst yes yes (default 20 / 200) yes yes
global_max_rps, global_burst yes yes yes yes
adaptive, min_rps yes yes yes yes
breaker_threshold, breaker_cooldown_seconds yes (per operation for EC2) yes yes yes
max_concurrency per API call, per account per HTTP attempt, per subscription per concurrent listing, per project or organization per call
retry_budget yes, stops botocore's retries yes, stops azure-core's retries yes, stops api_core's retries yes
max_retries no: botocore uses aws.max_retries retry_total and retry_status consecutive retries per page yes
max_backoff_seconds no: botocore's own backoff retry_backoff_max api_core Retry maximum yes
deadline_seconds no: botocore's timeouts and aws.max_retries bound a call RetryPolicy timeout (whole operation) api_core Retry timeout yes
aws.max_retries, aws.retry_mode botocore retries (counted after the first attempt; default adaptive, 10) n/a n/a n/a
live_*, <provider>.live_cooldown_seconds LiveOperationGuard only

In every integration the first two retries of a call (of a page, for GCP) are free and never draw on retry_budget.

Resource Graph pages fetched through _fetch_page with a client from a custom factory also retry a 429 up to QueryLimits.max_retries (5) times themselves; clients cloudg builds leave that to azure-core (section 3.3).

5.5 Examples

An organization-wide AWS map with many accounts, plus Azure and GCP estates that other teams also query. This leaves more of each account's quota to everyone else and keeps one account from absorbing the whole run:

ratelimit:
  aws:
    max_rps: 8                 # every account x region x service bucket
    burst: 16
    account_max_rps: 40        # all services of one account together
    global_max_rps: 200        # all of AWS from this process
    max_concurrency: 64        # requests in flight per account
    min_rps: 0.1
    breaker_cooldown_seconds: 120
    services:
      ec2: {max_rps: 10, burst: 50}            # still one bucket per EC2 action
      iam: {max_rps: 4, burst: 8}
      cloudcontrol: {max_rps: 2, burst: 4}
  azure:
    account_max_rps: 10        # per subscription
    services:
      resourcegraph: {max_rps: 1, burst: 5}
  gcp:
    services:
      cloudasset.ListAssets: {max_rps: 0.5, burst: 5}
  live_cooldown_seconds: 600

One noisy service. The tagging API in this account is shared with a cost tool that already uses most of its quota, and one AMI-heavy region needs its attribute calls slowed down without touching the rest of EC2:

ratelimit:
  aws:
    services:
      resourcegroupstaggingapi: {max_rps: 1, burst: 2}
      ec2.DescribeImageAttribute: {max_rps: 5, burst: 10}

Turning it off, everywhere or for one provider:

ratelimit:
  enabled: false
ratelimit:
  gcp:
    enabled: false

All four examples were loaded through CloudGConfig.model_validate and Governor(config) to check the resulting limits. In code:

from cloudg import CloudGConfig

config = CloudGConfig.model_validate(
    {"ratelimit": {"aws": {"max_rps": 8, "services": {"iam": {"max_rps": 4}}}}}
)
config.ratelimit.live_cooldown_seconds = 600

The shipped config.yaml has a commented ratelimit section with the defaults.