Skip to content

CLI Reference

Commands

zae-limiter

zae-limiter infrastructure management CLI.

Usage:

zae-limiter [OPTIONS] COMMAND [ARGS]...

Options:

Name Type Description Default
--version boolean Show the version and exit. Sentinel.UNSET
--help boolean Show this message and exit. Sentinel.UNSET

Subcommands

  • audit: Audit log commands.
  • cfn-template: Export CloudFormation template for custom deployment.
  • check: Check infrastructure compatibility without modifying.
  • delete: Delete CloudFormation stack and all resources.
  • deploy: Deploy CloudFormation stack with DynamoDB table and Lambda aggregator.
  • entity: Entity-level limit configuration.
  • lambda-export: Export Lambda deployment package for custom deployment.
  • limits: Declarative limits management.
  • list: List all deployed rate limiter instances in the region.
  • loadtest: Load testing commands for zae-limiter.
  • local: Local development with LocalStack.
  • namespace: Namespace management commands.
  • resource: Resource-level default limit configuration.
  • status: Get comprehensive status of rate limiter infrastructure.
  • system: System-level default limit configuration.
  • upgrade: Upgrade infrastructure to match client version.
  • usage: Usage snapshot commands.
  • version: Show infrastructure version information.

zae-limiter audit

Audit log commands.

Query audit events for entities. Events track configuration changes like limits_set, entity_created, and entity_deleted.

Usage:

zae-limiter audit [OPTIONS] COMMAND [ARGS]...

Options:

Name Type Description Default
--help boolean Show this message and exit. Sentinel.UNSET

Subcommands

  • list: List audit events for an entity.
zae-limiter audit list

List audit events for an entity.

Shows configuration changes like limits_set, entity_created, entity_deleted. Results are ordered by timestamp (newest first).

Examples:

zae-limiter audit list --entity-id user-123
zae-limiter audit list --entity-id user-123 --limit 10

Sample Output:

Audit Events for: user-123

Timestamp                Action         Principal   Resource
───────────────────────  ─────────────  ──────────  ────────
2026-01-15T10:30:00Z     limits_set     admin       gpt-4
2026-01-15T10:25:00Z     entity_created admin       -

Total: 2 events

Usage:

zae-limiter audit list [OPTIONS]

Options:

Name Type Description Default
--name, -n text Resource identifier used as the CloudFormation stack name. zae-limiter
--region text AWS region (default: use boto3 defaults) Sentinel.UNSET
--endpoint-url text AWS endpoint URL (e.g., http://localhost:4566 for LocalStack, or other AWS-compatible services) Sentinel.UNSET
--entity-id, -e text Entity ID to query audit events for Sentinel.UNSET
--limit, -l integer Maximum number of events to return (default: 100) 100
--start-event-id text Event ID to start after (for pagination) Sentinel.UNSET
--namespace, -N text Namespace within the table (default: "default") default
--help boolean Show this message and exit. Sentinel.UNSET

zae-limiter cfn-template

Export CloudFormation template for custom deployment.

Outputs the raw CloudFormation YAML template for manual deployment, integration with CDK/Terraform, or customization.

Examples:

# Export to file
zae-limiter cfn-template --output template.yaml

# Pipe to stdout
zae-limiter cfn-template > template.yaml

# View in pager
zae-limiter cfn-template | less

Usage:

zae-limiter cfn-template [OPTIONS]

Options:

Name Type Description Default
--output, -o path Output file (default: stdout) Sentinel.UNSET
--help boolean Show this message and exit. Sentinel.UNSET

zae-limiter check

Check infrastructure compatibility without modifying.

Verifies that the client version is compatible with the deployed infrastructure. Read-only operation - does not change anything: a Lambda behind the client is reported as an available update (apply it with 'upgrade'), and a missing stack is reported as NOT INITIALIZED.

Examples:

zae-limiter check --name my-app --region us-east-1
zae-limiter check --endpoint-url http://localhost:4566

Sample Output:

Compatibility Check
====================

Client:      0.6.0
Schema:      0.6.0
Lambda:      0.6.0

Result: COMPATIBLE

Client and infrastructure are fully compatible.

Usage:

zae-limiter check [OPTIONS]

Options:

Name Type Description Default
--name, -n text Resource identifier used as the CloudFormation stack name. zae-limiter
--region text AWS region (default: use boto3 defaults) Sentinel.UNSET
--endpoint-url text AWS endpoint URL (e.g., http://localhost:4566 for LocalStack, or other AWS-compatible services) Sentinel.UNSET
--help boolean Show this message and exit. Sentinel.UNSET

zae-limiter delete

Delete CloudFormation stack and all resources.

Removes the DynamoDB table, Lambda function, IAM roles, and all associated resources. This action cannot be undone - all data will be permanently lost.

Examples:

# Delete with confirmation prompt
zae-limiter delete --name my-app --region us-east-1

# Skip confirmation (for scripts)
zae-limiter delete --name my-app --yes

# Delete without waiting
zae-limiter delete --name my-app --no-wait

Data Loss

Deleting a stack removes the DynamoDB table and all its data. This action cannot be undone.

Usage:

zae-limiter delete [OPTIONS]

Options:

Name Type Description Default
--name, -n text Resource identifier used as the CloudFormation stack name Sentinel.UNSET
--region text AWS region (default: use boto3 defaults) Sentinel.UNSET
--endpoint-url text AWS endpoint URL (e.g., http://localhost:4566 for LocalStack, or other AWS-compatible services) Sentinel.UNSET
--wait / --no-wait boolean Wait for stack deletion to complete True
--yes, -y boolean Skip confirmation prompt Sentinel.UNSET
--help boolean Show this message and exit. Sentinel.UNSET

zae-limiter deploy

Deploy CloudFormation stack with DynamoDB table and Lambda aggregator.

Creates or updates infrastructure including DynamoDB table, Lambda aggregator for usage snapshots, CloudWatch alarms, and IAM roles. On first deploy, also registers the "default" namespace. The stack is idempotent - running deploy again updates existing resources.

Examples:

# Basic deployment
zae-limiter deploy --name my-app --region us-east-1

# Production with deletion protection and tracing
zae-limiter deploy --name prod --region us-east-1 \
    --enable-deletion-protection --enable-tracing

# Without Lambda aggregator (table only)
zae-limiter deploy --name simple --no-aggregator

# LocalStack development
zae-limiter deploy --name dev \
    --endpoint-url http://localhost:4566

# Enterprise with permission boundary
zae-limiter deploy --name prod \
    --permission-boundary arn:aws:iam::aws:policy/PowerUserAccess \
    --role-name-format "pb-{}-PowerUser"

Usage:

zae-limiter deploy [OPTIONS]

Options:

Name Type Description Default
--name, -n text Resource identifier used as the CloudFormation stack name. zae-limiter
--region text AWS region (default: use boto3 defaults) Sentinel.UNSET
--endpoint-url text AWS endpoint URL (e.g., http://localhost:4566 for LocalStack, or other AWS-compatible services) Sentinel.UNSET
--snapshot-windows text Comma-separated list of snapshot windows hourly,daily
--usage-retention-days integer Number of days to retain usage snapshots 90
--audit-retention-days integer Number of days to retain audit records (default: 90) 90
--enable-aggregator / --no-aggregator boolean Deploy Lambda aggregator for usage snapshots True
--enable-provisioner / --no-provisioner boolean Deploy Lambda provisioner for declarative limits True
--pitr-recovery-days integer Point-in-Time Recovery period in days (1-35, default: AWS default of 35) Sentinel.UNSET
--log-retention-days choice (1 | 3 | 5 | 7 | 14 | 30 | 60 | 90 | 120 | 150 | 180 | 365 | 400 | 545 | 731 | 1096 | 1827 | 2192 | 2557 | 2922 | 3288 | 3653) Number of days to retain Lambda logs (CloudWatch standard retention periods) 30
--lambda-timeout integer range (between 1 and 900) Lambda timeout in seconds (1-900, default: 60) 60
--lambda-memory integer range (between 128 and 3008) Lambda memory size in MB (128-3008, default: 256) 256
--enable-alarms / --no-alarms boolean Deploy CloudWatch alarms for monitoring (default: enabled) True
--alarm-sns-topic text SNS topic ARN for alarm notifications (optional) None
--lambda-duration-threshold-pct integer range (between 1 and 100) Lambda duration alarm threshold as percentage of timeout (1-100, default: 80) 80
--wait / --no-wait boolean Wait for stack creation to complete True
--permission-boundary text IAM permission boundary for Lambda role (policy name or full ARN) None
--role-name-format text Format template for role name. Use {} as placeholder for default name. Example: 'pb-{}' produces 'pb-mystack-aggr'. None
--policy-name-format text Format template for managed policy name. Use {} as placeholder for default name. Example: 'pb-{}' produces 'pb-mystack-app'. None
--enable-audit-archival / --no-audit-archival boolean Archive expired audit events to S3 (default: enabled) True
--audit-archive-glacier-days integer range (between 1 and 3650) Days before transitioning audit archives to Glacier Instant Retrieval (default: 90) 90
--enable-tracing / --no-tracing boolean Enable AWS X-Ray tracing for Lambda aggregator (default: disabled) False
--create-iam-roles / --no-create-iam-roles boolean Create App/Admin/ReadOnly IAM roles (default: disabled). Policies always created. False
--iam / --no-iam boolean Create IAM resources (policies, roles). --no-iam skips all IAM. True
--aggregator-role-arn text Use existing IAM role ARN for Lambda aggregator (enables aggregator with --no-iam). None
--enable-deletion-protection / --no-deletion-protection boolean Enable DynamoDB table deletion protection (default: disabled) False
--tag, -t text User-defined tag in KEY=VALUE format. Can be specified multiple times. Sentinel.UNSET
--help boolean Show this message and exit. Sentinel.UNSET

zae-limiter entity

Entity-level limit configuration.

Manage entities (users, API keys, projects) and their custom limits. Entity limits have highest priority, overriding resource and system defaults.

Usage:

zae-limiter entity [OPTIONS] COMMAND [ARGS]...

Options:

Name Type Description Default
--help boolean Show this message and exit. Sentinel.UNSET

Subcommands

  • bypass: Bypass an entity: admit every request, debit nothing, keep counting.
  • clear-cascade: Clear an entity's cascade policy, reverting to inherit.
  • clear-disabled: Clear an entity's explicit disabled flag, reverting to inherit.
  • create: Create a new entity.
  • delete-limits: Delete limits for a specific entity and resource.
  • disable: Disable an entity.
  • enable: Explicitly enable an entity, as an override.
  • get-limits: Get limits for a specific entity and resource.
  • list: List entities with custom limit configurations.
  • list-resources: List resources with entity-level custom limit configurations.
  • reset: Restore an entity's balance on one resource to its full share, now.
  • set-cascade: Set whether an entity cascades to its parent.
  • set-limits: Set limits for a specific entity and resource.
  • set-parent: Move an entity to a new parent, or to no parent.
  • show: Show details for an entity.
  • top-up: Add tokens to an entity's balance on one resource, now.
zae-limiter entity bypass

Bypass an entity: admit every request, debit nothing, keep counting.

ENTITY_ID is the entity to bypass (e.g., 'user-123', 'api-key-abc').

Omit --resource to bypass the entity on every resource (targets its _default_ config). Re-admits the entity to a disabled resource too. A bypass never extends to the entity's cascade parent. Lift it with entity clear-disabled. Needs the stack's Lambdas at 0.17.0 or later.

Examples:

zae-limiter entity bypass user-123
zae-limiter entity bypass user-123 --resource gpt-4

Usage:

zae-limiter entity bypass [OPTIONS] ENTITY_ID

Options:

Name Type Description Default
--resource text Resource to scope to. Omit to apply across all resources for this entity. None
--name, -n text Stack identifier used as the CloudFormation stack name. zae-limiter
--region text AWS region (default: use boto3 defaults) Sentinel.UNSET
--endpoint-url text AWS endpoint URL (e.g., http://localhost:4566 for LocalStack) Sentinel.UNSET
--namespace, -N text Namespace within the table (default: "default") default
--help boolean Show this message and exit. Sentinel.UNSET
zae-limiter entity clear-cascade

Clear an entity's cascade policy, reverting to inherit.

ENTITY_ID is the entity to clear (e.g., 'user-123'). Omit --resource to clear its entity-wide policy (the entity's _default_ config).

Examples:

zae-limiter entity clear-cascade user-123 --resource gpt-4

Usage:

zae-limiter entity clear-cascade [OPTIONS] ENTITY_ID

Options:

Name Type Description Default
--resource text Resource to scope to. Omit to apply across all resources for this entity. None
--name, -n text Stack identifier used as the CloudFormation stack name. zae-limiter
--region text AWS region (default: use boto3 defaults) Sentinel.UNSET
--endpoint-url text AWS endpoint URL (e.g., http://localhost:4566 for LocalStack) Sentinel.UNSET
--namespace, -N text Namespace within the table (default: "default") default
--help boolean Show this message and exit. Sentinel.UNSET
zae-limiter entity clear-disabled

Clear an entity's explicit disabled flag, reverting to inherit.

ENTITY_ID is the entity to clear (e.g., 'user-123', 'api-key-abc'). Removes any explicit disable/enable value, so the entity resolves whatever it would inherit from the resource level (there is no system level). Omit --resource to apply across every resource for this entity (targets the entity's _default_ config).

Examples:

zae-limiter entity clear-disabled user-123 --resource gpt-4

Usage:

zae-limiter entity clear-disabled [OPTIONS] ENTITY_ID

Options:

Name Type Description Default
--resource text Resource to scope to. Omit to apply across all resources for this entity. None
--name, -n text Stack identifier used as the CloudFormation stack name. zae-limiter
--region text AWS region (default: use boto3 defaults) Sentinel.UNSET
--endpoint-url text AWS endpoint URL (e.g., http://localhost:4566 for LocalStack) Sentinel.UNSET
--namespace, -N text Namespace within the table (default: "default") default
--help boolean Show this message and exit. Sentinel.UNSET
zae-limiter entity create

Create a new entity.

ENTITY_ID is the unique identifier for the entity (e.g., 'user-123', 'api-key-abc').

Examples:

# Create a standalone entity
zae-limiter entity create user-123

# Create with display name
zae-limiter entity create api-key-abc --display-name "Production API"

# Create with parent and cascade
zae-limiter entity create user-123 --parent org-456 --cascade

Usage:

zae-limiter entity create [OPTIONS] ENTITY_ID

Options:

Name Type Description Default
--display-name text Human-readable name (defaults to entity_id) None
--parent text Parent entity ID (for hierarchical limits) None
--cascade / --no-cascade boolean Enable cascade: acquire() also consumes from parent entity False
--name, -n text Stack identifier used as the CloudFormation stack name. zae-limiter
--region text AWS region (default: use boto3 defaults) Sentinel.UNSET
--endpoint-url text AWS endpoint URL (e.g., http://localhost:4566 for LocalStack) Sentinel.UNSET
--namespace, -N text Namespace within the table (default: "default") default
--help boolean Show this message and exit. Sentinel.UNSET
zae-limiter entity delete-limits

Delete limits for a specific entity and resource.

ENTITY_ID is the entity to delete limits from (e.g., 'user-123', 'api-key-abc').

Examples:

# Delete with confirmation
zae-limiter entity delete-limits user-premium --resource gpt-4

# Skip confirmation
zae-limiter entity delete-limits user-premium -r gpt-4 --yes

Usage:

zae-limiter entity delete-limits [OPTIONS] ENTITY_ID

Options:

Name Type Description Default
--resource, -r text Resource name (e.g., 'gpt-4', 'default' for all resources). Default: default _default_
--name, -n text Stack identifier used as the CloudFormation stack name. zae-limiter
--region text AWS region (default: use boto3 defaults) Sentinel.UNSET
--endpoint-url text AWS endpoint URL (e.g., http://localhost:4566 for LocalStack) Sentinel.UNSET
--yes, -y boolean Skip confirmation prompt Sentinel.UNSET
--namespace, -N text Namespace within the table (default: "default") default
--help boolean Show this message and exit. Sentinel.UNSET
zae-limiter entity disable

Disable an entity.

ENTITY_ID is the entity to disable (e.g., 'user-123', 'api-key-abc').

Omit --resource to disable the entity across every resource (targets the entity's _default_ config). Existing buckets are stamped immediately, so the change takes effect on the next request.

Examples:

zae-limiter entity disable user-123
zae-limiter entity disable user-123 --resource gpt-4

Usage:

zae-limiter entity disable [OPTIONS] ENTITY_ID

Options:

Name Type Description Default
--resource text Resource to scope to. Omit to apply across all resources for this entity. None
--name, -n text Stack identifier used as the CloudFormation stack name. zae-limiter
--region text AWS region (default: use boto3 defaults) Sentinel.UNSET
--endpoint-url text AWS endpoint URL (e.g., http://localhost:4566 for LocalStack) Sentinel.UNSET
--namespace, -N text Namespace within the table (default: "default") default
--help boolean Show this message and exit. Sentinel.UNSET
zae-limiter entity enable

Explicitly enable an entity, as an override.

ENTITY_ID is the entity to enable (e.g., 'user-123', 'api-key-abc').

This is an override: it re-admits one entity to a resource that is disabled at the resource level, while everyone else stays blocked. Omit --resource to apply the override across every resource for this entity (targets the entity's _default_ config).

Examples:

zae-limiter entity enable user-123 --resource gpt-4

Usage:

zae-limiter entity enable [OPTIONS] ENTITY_ID

Options:

Name Type Description Default
--resource text Resource to scope to. Omit to apply across all resources for this entity. None
--name, -n text Stack identifier used as the CloudFormation stack name. zae-limiter
--region text AWS region (default: use boto3 defaults) Sentinel.UNSET
--endpoint-url text AWS endpoint URL (e.g., http://localhost:4566 for LocalStack) Sentinel.UNSET
--namespace, -N text Namespace within the table (default: "default") default
--help boolean Show this message and exit. Sentinel.UNSET
zae-limiter entity get-limits

Get limits for a specific entity and resource.

ENTITY_ID is the entity to query (e.g., 'user-123', 'api-key-abc').

Examples:

zae-limiter entity get-limits user-premium --resource gpt-4
zae-limiter entity get-limits api-key-123 -r claude-3

Sample Output:

Limits for entity 'user-premium' on resource 'gpt-4':
  rpm: 1000/min
  tpm: 100000/min

Usage:

zae-limiter entity get-limits [OPTIONS] ENTITY_ID

Options:

Name Type Description Default
--resource, -r text Resource name (e.g., 'gpt-4', 'default' for all resources). Default: default _default_
--name, -n text Stack identifier used as the CloudFormation stack name. zae-limiter
--region text AWS region (default: use boto3 defaults) Sentinel.UNSET
--endpoint-url text AWS endpoint URL (e.g., http://localhost:4566 for LocalStack) Sentinel.UNSET
--namespace, -N text Namespace within the table (default: "default") default
--help boolean Show this message and exit. Sentinel.UNSET
zae-limiter entity list

List entities with custom limit configurations.

Uses GSI3 sparse index for efficient queries.

Examples:

# List entities with custom limits for gpt-4
zae-limiter entity list --with-custom-limits gpt-4

# List with a maximum of 10 results
zae-limiter entity list --with-custom-limits claude-3 --limit 10

Usage:

zae-limiter entity list [OPTIONS]

Options:

Name Type Description Default
--with-custom-limits text List entities with custom limits for this resource Sentinel.UNSET
--limit integer Maximum number of entities to return None
--name, -n text Stack identifier used as the CloudFormation stack name. zae-limiter
--region text AWS region (default: use boto3 defaults) Sentinel.UNSET
--endpoint-url text AWS endpoint URL (e.g., http://localhost:4566 for LocalStack) Sentinel.UNSET
--namespace, -N text Namespace within the table (default: "default") default
--help boolean Show this message and exit. Sentinel.UNSET
zae-limiter entity list-resources

List resources with entity-level custom limit configurations.

Shows which resources have at least one entity with custom limits. Uses the entity config resources registry for fast O(1) lookup.

Examples:

zae-limiter entity list-resources
zae-limiter entity list-resources --name prod

Sample Output:

Resources with entity-level custom limits:
  gpt-4
  claude-3

Usage:

zae-limiter entity list-resources [OPTIONS]

Options:

Name Type Description Default
--name, -n text Stack identifier used as the CloudFormation stack name. zae-limiter
--region text AWS region (default: use boto3 defaults) Sentinel.UNSET
--endpoint-url text AWS endpoint URL (e.g., http://localhost:4566 for LocalStack) Sentinel.UNSET
--namespace, -N text Namespace within the table (default: "default") default
--help boolean Show this message and exit. Sentinel.UNSET
zae-limiter entity reset

Restore an entity's balance on one resource to its full share, now.

ENTITY_ID is the entity (e.g., 'user-123'). Every shard of the bucket is restored in one transaction: a dripping limit to its ceiling (debt is forgiven), a calendar quota to its share as a new period, a session quota to its share with its window ended, so the next request opens a fresh one. The consumption counter, the disabled flag, config and the parent's buckets are left alone. A bucket that does not exist yet is left alone too.

Examples:

zae-limiter entity reset user-123 --resource gpt-4
zae-limiter entity reset user-123 -r claude --limit session

Usage:

zae-limiter entity reset [OPTIONS] ENTITY_ID

Options:

Name Type Description Default
--resource, -r text Resource to reset (one at a time). Sentinel.UNSET
--limit, -l text Limit to reset (repeatable). Omit to reset every limit on the resource. Sentinel.UNSET
--idempotency-key text Name this operation (1-64 of letters, digits, . _ : -) so a retry with the same key within three days is applied once. Without one, an error leaves the outcome unknown. None
--name, -n text Stack identifier used as the CloudFormation stack name. zae-limiter
--region text AWS region (default: use boto3 defaults) Sentinel.UNSET
--endpoint-url text AWS endpoint URL (e.g., http://localhost:4566 for LocalStack) Sentinel.UNSET
--namespace, -N text Namespace within the table (default: "default") default
--help boolean Show this message and exit. Sentinel.UNSET
zae-limiter entity set-cascade

Set whether an entity cascades to its parent.

ENTITY_ID is the entity (e.g., 'user-123'); VALUE is 'on' or 'off'. Omit --resource to set it for every resource that has no policy of its own (targets the entity's _default_ config). Existing buckets are restamped immediately. Requires a stack whose Lambdas are 0.16.0 or later (run 'zae-limiter upgrade' first if not).

Examples:

zae-limiter entity set-cascade user-123 on --resource gpt-4
zae-limiter entity set-cascade user-123 off

Usage:

zae-limiter entity set-cascade [OPTIONS] ENTITY_ID {on|off}

Options:

Name Type Description Default
--resource text Resource to scope to. Omit to apply across all resources for this entity. None
--name, -n text Stack identifier used as the CloudFormation stack name. zae-limiter
--region text AWS region (default: use boto3 defaults) Sentinel.UNSET
--endpoint-url text AWS endpoint URL (e.g., http://localhost:4566 for LocalStack) Sentinel.UNSET
--namespace, -N text Namespace within the table (default: "default") default
--help boolean Show this message and exit. Sentinel.UNSET
zae-limiter entity set-limits

Set limits for a specific entity and resource.

ENTITY_ID is the entity to configure (e.g., 'user-123', 'api-key-abc'). Entity limits override resource and system defaults.

Examples:

# Set premium user limits for gpt-4
zae-limiter entity set-limits user-premium -r gpt-4 -l tpm:100000 -l rpm:1000

# Set limits for claude-3 with per-hour period
zae-limiter entity set-limits api-key-123 -r claude-3 -l tph:50000/hour

Usage:

zae-limiter entity set-limits [OPTIONS] ENTITY_ID

Options:

Name Type Description Default
--resource, -r text Resource name (e.g., 'gpt-4', 'default' for all resources). Default: default _default_
--name, -n text Stack identifier used as the CloudFormation stack name. zae-limiter
--region text AWS region (default: use boto3 defaults) Sentinel.UNSET
--endpoint-url text AWS endpoint URL (e.g., http://localhost:4566 for LocalStack) Sentinel.UNSET
--limit, -l text Limit in 'name:rate[/period]' or 'name:rate[/period]:burst' format (repeatable). Period: /sec, /min (default), /hour, /day. Sentinel.UNSET
--soft text Make the named limit soft: metered and debited, but never a reason to reject (repeatable). Must name a limit given with -l. Sentinel.UNSET
--namespace, -N text Namespace within the table (default: "default") default
--help boolean Show this message and exit. Sentinel.UNSET
zae-limiter entity set-parent

Move an entity to a new parent, or to no parent.

ENTITY_ID is the entity to move (e.g., 'user-123'). Give exactly one of --parent or --none. Existing buckets are restamped immediately, and every process debits the new parent from its next acquire. Usage already charged to the old parent stays there. Whether the entity debits its new parent follows its cascade policy (see set-cascade). Requires a stack whose Lambdas are 0.17.0 or later (run 'zae-limiter upgrade' first if not).

Examples:

zae-limiter entity set-parent user-123 --parent org-b
zae-limiter entity set-parent user-123 --none

Usage:

zae-limiter entity set-parent [OPTIONS] ENTITY_ID

Options:

Name Type Description Default
--parent text The new parent (must exist). None
--none boolean Move the entity to no parent. Sentinel.UNSET
--name, -n text Stack identifier used as the CloudFormation stack name. zae-limiter
--region text AWS region (default: use boto3 defaults) Sentinel.UNSET
--endpoint-url text AWS endpoint URL (e.g., http://localhost:4566 for LocalStack) Sentinel.UNSET
--namespace, -N text Namespace within the table (default: "default") default
--help boolean Show this message and exit. Sentinel.UNSET
zae-limiter entity show

Show details for an entity.

ENTITY_ID is the entity to query (e.g., 'user-123', 'api-key-abc').

Examples:

zae-limiter entity show user-123
zae-limiter entity show api-key-abc --name prod

Sample Output:

Entity: user-123
  Name:       Alice Smith
  Parent:     org-456
  Cascade:    True
  Created:    2026-01-15T10:30:00Z
  Metadata:   {'tier': 'premium'}

Usage:

zae-limiter entity show [OPTIONS] ENTITY_ID

Options:

Name Type Description Default
--name, -n text Stack identifier used as the CloudFormation stack name. zae-limiter
--region text AWS region (default: use boto3 defaults) Sentinel.UNSET
--endpoint-url text AWS endpoint URL (e.g., http://localhost:4566 for LocalStack) Sentinel.UNSET
--namespace, -N text Namespace within the table (default: "default") default
--help boolean Show this message and exit. Sentinel.UNSET
zae-limiter entity top-up

Add tokens to an entity's balance on one resource, now.

ENTITY_ID is the entity (e.g., 'user-123'). A quota gains exactly N, above its plan if need be, until its next reset or window end; a session quota with no live window opens one. A dripping limit gains at most the room below its ceiling. A quota top-up needs a stack whose Lambdas are 0.17.0 or later (run 'zae-limiter upgrade' first if not).

Examples:

zae-limiter entity top-up user-123 -r claude --add session:5000
zae-limiter entity top-up user-123 -r gpt-4 --add rpd:100 --add tpd:50000

Usage:

zae-limiter entity top-up [OPTIONS] ENTITY_ID

Options:

Name Type Description Default
--resource, -r text Resource to top up. Sentinel.UNSET
--add, -a text LIMIT:N — add N whole tokens to LIMIT (repeatable). Sentinel.UNSET
--idempotency-key text Name this operation (1-64 of letters, digits, . _ : -) so a retry with the same key within three days is applied once. Without one, an error leaves the outcome unknown. None
--name, -n text Stack identifier used as the CloudFormation stack name. zae-limiter
--region text AWS region (default: use boto3 defaults) Sentinel.UNSET
--endpoint-url text AWS endpoint URL (e.g., http://localhost:4566 for LocalStack) Sentinel.UNSET
--namespace, -N text Namespace within the table (default: "default") default
--help boolean Show this message and exit. Sentinel.UNSET

zae-limiter lambda-export

Export Lambda deployment package for custom deployment.

Creates a ZIP file containing the Lambda aggregator code for manual deployment or inspection. Useful for custom deployment pipelines.

Examples:

# Export Lambda package
zae-limiter lambda-export --output lambda.zip

# Show package info without building
zae-limiter lambda-export --info

# Overwrite existing file
zae-limiter lambda-export --force

Sample Output (--info):

Lambda Package Information
==========================

Package path:      /path/to/zae_limiter_aggregator
Python files:      4
Uncompressed size: 24.5 KB
Handler:           zae_limiter_aggregator.handler.handler
Dependencies:      1
  - aws-lambda-powertools

Usage:

zae-limiter lambda-export [OPTIONS]

Options:

Name Type Description Default
--output, -o path Output file path (default: lambda.zip) lambda.zip
--info boolean Show package information without building Sentinel.UNSET
--force, -f boolean Overwrite existing file without prompting Sentinel.UNSET
--help boolean Show this message and exit. Sentinel.UNSET

zae-limiter limits

Declarative limits management.

Manage rate limits via YAML files. Apply through a Lambda provisioner that supports both CLI and CloudFormation paths.

Usage:

zae-limiter limits [OPTIONS] COMMAND [ARGS]...

Options:

Name Type Description Default
--help boolean Show this message and exit. Sentinel.UNSET

Subcommands

  • apply: Apply limits from YAML file (like terraform apply).
  • cfn-template: Generate a CloudFormation template from YAML file.
  • diff: Show drift between YAML and live DynamoDB state.
  • plan: Preview changes without applying (like terraform plan).
zae-limiter limits apply

Apply limits from YAML file (like terraform apply).

Usage:

zae-limiter limits apply [OPTIONS]

Options:

Name Type Description Default
--name, -n text Stack identifier. Sentinel.UNSET
--region text AWS region. Sentinel.UNSET
--endpoint-url text AWS endpoint URL (e.g., LocalStack). Sentinel.UNSET
--namespace, -N text Namespace. default
--file, -f path YAML limits file. Sentinel.UNSET
--quiet, -q boolean Print only the summary, not a line per changed entry. Sentinel.UNSET
--full boolean Rewrite and fan out every declared entry, not only the ones that differ from the table. Repairs bucket items an earlier fan-out missed. Sentinel.UNSET
--help boolean Show this message and exit. Sentinel.UNSET
zae-limiter limits cfn-template

Generate a CloudFormation template from YAML file.

Usage:

zae-limiter limits cfn-template [OPTIONS]

Options:

Name Type Description Default
--name, -n text Stack identifier (for ImportValue). Sentinel.UNSET
--file, -f path YAML limits file. Sentinel.UNSET
--full boolean Emit FullApply: true, so every stack update applies in full, like 'limits apply --full'. Repairs bucket items an earlier fan-out missed. Sentinel.UNSET
--help boolean Show this message and exit. Sentinel.UNSET
zae-limiter limits diff

Show drift between YAML and live DynamoDB state.

Read-only, with the same refusals as 'limits plan': a missing stack or namespace, or a stack whose Lambdas are behind this client.

Usage:

zae-limiter limits diff [OPTIONS]

Options:

Name Type Description Default
--name, -n text Stack identifier. Sentinel.UNSET
--region text AWS region. Sentinel.UNSET
--endpoint-url text AWS endpoint URL (e.g., LocalStack). Sentinel.UNSET
--namespace, -N text Namespace. default
--file, -f path YAML limits file. Sentinel.UNSET
--quiet, -q boolean Print only the summary, not a line per changed entry. Sentinel.UNSET
--help boolean Show this message and exit. Sentinel.UNSET
zae-limiter limits plan

Preview changes without applying (like terraform plan).

Read-only: never deploys a stack, registers a namespace, writes the version record or updates a Lambda. A missing stack or namespace is an error, and so is a stack whose Lambdas are behind this client — the provisioner does the planning, so run 'zae-limiter upgrade' first.

Usage:

zae-limiter limits plan [OPTIONS]

Options:

Name Type Description Default
--name, -n text Stack identifier. Sentinel.UNSET
--region text AWS region. Sentinel.UNSET
--endpoint-url text AWS endpoint URL (e.g., LocalStack). Sentinel.UNSET
--namespace, -N text Namespace. default
--file, -f path YAML limits file. Sentinel.UNSET
--quiet, -q boolean Print only the summary, not a line per changed entry. Sentinel.UNSET
--help boolean Show this message and exit. Sentinel.UNSET

zae-limiter list

List all deployed rate limiter instances in the region.

Discovers stacks by CloudFormation tags. Shows name, status, version, and creation date for each instance.

Examples:

zae-limiter list --region us-east-1
zae-limiter list --endpoint-url http://localhost:4566

Sample Output:

Rate Limiter Instances (us-east-1)

Name        Status             Version   Created
──────────  ─────────────────  ────────  ──────────
my-app      CREATE_COMPLETE    0.6.0     2026-01-15
prod-api    UPDATE_COMPLETE    0.6.0     2026-01-10

Usage:

zae-limiter list [OPTIONS]

Options:

Name Type Description Default
--region text AWS region (default: use boto3 defaults) Sentinel.UNSET
--endpoint-url text AWS endpoint URL (e.g., http://localhost:4566 for LocalStack, or other AWS-compatible services) Sentinel.UNSET
--help boolean Show this message and exit. Sentinel.UNSET

zae-limiter loadtest

Load testing commands for zae-limiter.

Usage:

zae-limiter loadtest [OPTIONS] COMMAND [ARGS]...

Options:

Name Type Description Default
--help boolean Show this message and exit. Sentinel.UNSET

Subcommands

  • delete: Delete load test infrastructure.
  • deploy: Deploy load test infrastructure.
  • list: List deployed load test stacks.
  • push: Rebuild and push locustfiles and Lambda code.
  • run: Run a single load test execution.
  • tune: Find optimal per-worker user count via binary search.
  • ui: Open Locust web UI via SSM tunnel.
zae-limiter loadtest delete

Delete load test infrastructure.

Usage:

zae-limiter loadtest delete [OPTIONS]

Options:

Name Type Description Default
--name, -n text zae-limiter name Sentinel.UNSET
--region text AWS region None
--yes boolean Skip confirmation Sentinel.UNSET
--help boolean Show this message and exit. Sentinel.UNSET
zae-limiter loadtest deploy

Deploy load test infrastructure.

Usage:

zae-limiter loadtest deploy [OPTIONS]

Options:

Name Type Description Default
--name, -n text zae-limiter name None
--region text AWS region None
--vpc-id text VPC ID for load test resources None
--subnet-ids text Comma-separated private subnet IDs None
--max-workers integer Maximum Lambda workers (auto-scaling cap) 100
--users-per-worker integer Max users per Lambda worker for auto-scaling (default: 10) 10
--min-workers integer Minimum workers to maintain (default: 1) 1
--startup-lead-time integer Seconds to predict ahead for proactive scaling (default: 20) 20
--lambda-timeout integer Lambda worker timeout in minutes (default: 5) 5
--lambda-memory integer Lambda worker memory in MB (CPU scales with memory; 1769 MB = 1 vCPU, default: 1769) 1769
--capacity-provider choice (FARGATE_SPOT | FARGATE) ECS capacity provider (default: FARGATE_SPOT) FARGATE_SPOT
--ssm-endpoint / --no-ssm-endpoint boolean Create VPC endpoints for SSM (not needed if VPC has NAT gateway) False
--dynamodb-endpoint / --no-dynamodb-endpoint boolean Create DynamoDB gateway endpoint (auto-discovers route tables) True
-C directory Directory containing locustfiles (default: current directory) .
--help boolean Show this message and exit. Sentinel.UNSET
zae-limiter loadtest list

List deployed load test stacks.

Usage:

zae-limiter loadtest list [OPTIONS]

Options:

Name Type Description Default
--region text AWS region None
--help boolean Show this message and exit. Sentinel.UNSET
zae-limiter loadtest push

Rebuild and push locustfiles and Lambda code.

Usage:

zae-limiter loadtest push [OPTIONS]

Options:

Name Type Description Default
--name, -n text zae-limiter name None
--region text AWS region None
-C directory Directory containing locustfiles (default: current directory) .
--help boolean Show this message and exit. Sentinel.UNSET
zae-limiter loadtest run

Run a single load test execution.

Lambda mode (default): Invokes a single Lambda worker in headless mode. Use --workers N to run distributed (Fargate master + Lambda workers).

Optionally pass User class names to run specific classes (default: all).

Usage:

zae-limiter loadtest run [OPTIONS] [USER_CLASSES]...

Options:

Name Type Description Default
--name, -n text zae-limiter name Sentinel.UNSET
--region text AWS region None
--users integer Number of simulated users (default: 20) 20
--duration integer Test duration in seconds (default: 60) 60
--spawn-rate integer User spawn rate per second (default: 10) 10
-f, --locustfile text Locustfile path (e.g. locustfiles/max_rps.py) Sentinel.UNSET
--cpu integer Override Fargate task CPU units (default from task def) None
--memory integer Override Fargate task memory in MB (default from task def) None
--port integer Local port for SSM tunnel (Fargate mode) 8089
--workers integer Number of Lambda workers (implies distributed mode) None
--help boolean Show this message and exit. Sentinel.UNSET
zae-limiter loadtest tune

Find optimal per-worker user count via binary search.

Uses Little's Law to binary-search for the optimal per-worker user count by measuring efficiency (baseline_p50 / observed_p50) at different concurrency levels. Lambda-only.

Optionally pass User class names to run specific classes (default: all).

Usage:

zae-limiter loadtest tune [OPTIONS] [USER_CLASSES]...

Options:

Name Type Description Default
--name, -n text zae-limiter name Sentinel.UNSET
--region text AWS region None
-f, --locustfile text Locustfile path (e.g. locustfiles/max_rps.py) Sentinel.UNSET
--max-users integer Upper bound for binary search (default: 40) 40
--threshold float Target efficiency ratio (default: 0.80) 0.8
--step-duration integer Seconds per tuning step (default: 30) 30
--baseline-duration integer Seconds for baseline phase (default: 60) 60
--spawn-rate integer User spawn rate per second (default: 10) 10
--help boolean Show this message and exit. Sentinel.UNSET
zae-limiter loadtest ui

Open Locust web UI via SSM tunnel.

Usage:

zae-limiter loadtest ui [OPTIONS]

Options:

Name Type Description Default
--name, -n text zae-limiter name Sentinel.UNSET
--region text AWS region None
--port integer Local port for Locust UI 8089
--destroy boolean Stop Fargate on disconnect even if already running Sentinel.UNSET
--force boolean Stop existing task and restart with new config Sentinel.UNSET
-f, --locustfile text Locustfile path (relative to -C directory used in deploy) Sentinel.UNSET
--max-workers integer Override max Lambda workers None
--min-workers integer Override minimum workers None
--users-per-worker integer Override users per worker ratio None
--startup-lead-time integer Override predictive scaling lookahead None
--cpu integer Override task CPU units (256, 512, 1024, 2048, 4096) None
--memory integer Override task memory in MB None
--pool-connections integer Override boto3 connection pool size (default: 1000) None
--help boolean Show this message and exit. Sentinel.UNSET

zae-limiter local

Local development with LocalStack.

Requires the [local] extra:

pip install 'zae-limiter[local]'

Usage:

zae-limiter local [OPTIONS] COMMAND [ARGS]...

Options:

Name Type Description Default
--help boolean Show this message and exit. Sentinel.UNSET

Subcommands

  • down: Stop LocalStack.
  • env: Output LocalStack environment variables.
  • logs: Show LocalStack container logs.
  • status: Show LocalStack container status.
  • up: Start LocalStack for local development.
zae-limiter local down

Stop LocalStack.

Examples:

zae-limiter local down

Usage:

zae-limiter local down [OPTIONS]

Options:

Name Type Description Default
--docker-host text Docker daemon URL (e.g., unix:///path/to/docker.sock) Sentinel.UNSET
--help boolean Show this message and exit. Sentinel.UNSET
zae-limiter local env

Output LocalStack environment variables.

Prints the environment variables needed to connect to LocalStack. Does not require Docker or a running container.

Examples:

eval "$(zae-limiter local env)"                 # bash/zsh
zae-limiter local env --format direnv > .envrc  # direnv
zae-limiter local env --format powershell       # PowerShell

Usage:

zae-limiter local env [OPTIONS]

Options:

Name Type Description Default
--format, -f choice (eval | direnv | powershell) Output format eval
--port integer Host port for LocalStack endpoint 4566
--help boolean Show this message and exit. Sentinel.UNSET
zae-limiter local logs

Show LocalStack container logs.

Examples:

# Show recent logs
zae-limiter local logs

# Follow logs
zae-limiter local logs --follow

# Show last 50 lines
zae-limiter local logs --tail 50

Usage:

zae-limiter local logs [OPTIONS]

Options:

Name Type Description Default
--docker-host text Docker daemon URL (e.g., unix:///path/to/docker.sock) Sentinel.UNSET
--follow, -f boolean Follow log output Sentinel.UNSET
--tail integer Number of lines to show from end of logs 100
--help boolean Show this message and exit. Sentinel.UNSET
zae-limiter local status

Show LocalStack container status.

Examples:

zae-limiter local status

Sample Output:

LocalStack: running
Endpoint:   http://localhost:4566
Health:     healthy
Image:      localstack/localstack:4.14
Services:   dynamodb,dynamodbstreams,lambda,cloudformation,...

To configure your shell:
  eval "$(zae-limiter local env)"                 # bash/zsh
  zae-limiter local env --format direnv > .envrc  # direnv
  zae-limiter local env --format powershell       # PowerShell

Usage:

zae-limiter local status [OPTIONS]

Options:

Name Type Description Default
--docker-host text Docker daemon URL (e.g., unix:///path/to/docker.sock) Sentinel.UNSET
--help boolean Show this message and exit. Sentinel.UNSET
zae-limiter local up

Start LocalStack for local development.

Examples:

# Start LocalStack
zae-limiter local up

# Start with deploy instructions
zae-limiter local up --name my-app

# Use a different port
zae-limiter local up --port 4567

Usage:

zae-limiter local up [OPTIONS]

Options:

Name Type Description Default
--docker-host text Docker daemon URL (e.g., unix:///path/to/docker.sock) Sentinel.UNSET
--image text LocalStack Docker image localstack/localstack:4.14
--name, -n text Stack name to include in deploy instructions None
--port integer Host port to bind LocalStack to 4566
--help boolean Show this message and exit. Sentinel.UNSET

zae-limiter namespace

Namespace management commands.

Manage multi-tenant namespaces for isolated rate limiting. Each namespace has its own entities, buckets, and configurations.

Usage:

zae-limiter namespace [OPTIONS] COMMAND [ARGS]...

Options:

Name Type Description Default
--help boolean Show this message and exit. Sentinel.UNSET

Subcommands

  • delete: Soft-delete a namespace (recoverable).
  • list: List all active namespaces with IDs.
  • orphans: List deleted namespaces with orphaned data.
  • purge: Permanently delete all data for a namespace (IRREVERSIBLE).
  • recover: Recover a deleted namespace by its ID.
  • register: Register one or more namespaces.
  • show: Show details for a specific namespace.
zae-limiter namespace delete

Soft-delete a namespace (recoverable).

NAMESPACE_NAME is the namespace to delete (e.g., 'tenant-alpha'). Data items are NOT deleted — they remain orphaned and can be recovered.

Examples:

zae-limiter namespace delete tenant-alpha --name my-app --yes

Usage:

zae-limiter namespace delete [OPTIONS] NAMESPACE_NAME

Options:

Name Type Description Default
--name, -n text Stack identifier. zae-limiter
--region text AWS region (default: use boto3 defaults) Sentinel.UNSET
--endpoint-url text AWS endpoint URL (e.g., http://localhost:4566 for LocalStack) Sentinel.UNSET
--yes, -y boolean Skip confirmation prompt Sentinel.UNSET
--help boolean Show this message and exit. Sentinel.UNSET
zae-limiter namespace list

List all active namespaces with IDs.

Examples:

zae-limiter namespace list --name my-app

Usage:

zae-limiter namespace list [OPTIONS]

Options:

Name Type Description Default
--name, -n text Stack identifier. zae-limiter
--region text AWS region (default: use boto3 defaults) Sentinel.UNSET
--endpoint-url text AWS endpoint URL (e.g., http://localhost:4566 for LocalStack) Sentinel.UNSET
--help boolean Show this message and exit. Sentinel.UNSET
zae-limiter namespace orphans

List deleted namespaces with orphaned data.

Examples:

zae-limiter namespace orphans --name my-app

Usage:

zae-limiter namespace orphans [OPTIONS]

Options:

Name Type Description Default
--name, -n text Stack identifier. zae-limiter
--region text AWS region (default: use boto3 defaults) Sentinel.UNSET
--endpoint-url text AWS endpoint URL (e.g., http://localhost:4566 for LocalStack) Sentinel.UNSET
--help boolean Show this message and exit. Sentinel.UNSET
zae-limiter namespace purge

Permanently delete all data for a namespace (IRREVERSIBLE).

NAMESPACE_ID is the opaque namespace ID (e.g., 'aB3x_9Qw'). Use 'namespace orphans' to find deleted namespace IDs.

Examples:

zae-limiter namespace purge aB3x_9Qw --name my-app --yes

Data Loss

Purging permanently deletes all entities, buckets, configs, and audit logs in the namespace. This cannot be undone.

Usage:

zae-limiter namespace purge [OPTIONS] NAMESPACE_ID

Options:

Name Type Description Default
--name, -n text Stack identifier. zae-limiter
--region text AWS region (default: use boto3 defaults) Sentinel.UNSET
--endpoint-url text AWS endpoint URL (e.g., http://localhost:4566 for LocalStack) Sentinel.UNSET
--yes, -y boolean Skip confirmation prompt Sentinel.UNSET
--help boolean Show this message and exit. Sentinel.UNSET
zae-limiter namespace recover

Recover a deleted namespace by its ID.

NAMESPACE_ID is the opaque namespace ID (e.g., 'aB3x_9Qw'). Use 'namespace orphans' to find deleted namespace IDs.

Examples:

zae-limiter namespace recover aB3x_9Qw --name my-app

Usage:

zae-limiter namespace recover [OPTIONS] NAMESPACE_ID

Options:

Name Type Description Default
--name, -n text Stack identifier. zae-limiter
--region text AWS region (default: use boto3 defaults) Sentinel.UNSET
--endpoint-url text AWS endpoint URL (e.g., http://localhost:4566 for LocalStack) Sentinel.UNSET
--help boolean Show this message and exit. Sentinel.UNSET
zae-limiter namespace register

Register one or more namespaces.

NAMESPACES are the namespace names to register (e.g., 'tenant-alpha'). Multiple names can be provided for bulk registration.

Examples:

zae-limiter namespace register tenant-alpha --name my-app
zae-limiter namespace register tenant-alpha tenant-beta --name my-app

Usage:

zae-limiter namespace register [OPTIONS] NAMESPACES...

Options:

Name Type Description Default
--name, -n text Stack identifier. zae-limiter
--region text AWS region (default: use boto3 defaults) Sentinel.UNSET
--endpoint-url text AWS endpoint URL (e.g., http://localhost:4566 for LocalStack) Sentinel.UNSET
--help boolean Show this message and exit. Sentinel.UNSET
zae-limiter namespace show

Show details for a specific namespace.

NAMESPACE_NAME is the namespace to look up (e.g., 'tenant-alpha').

Examples:

zae-limiter namespace show tenant-alpha --name my-app

Usage:

zae-limiter namespace show [OPTIONS] NAMESPACE_NAME

Options:

Name Type Description Default
--name, -n text Stack identifier. zae-limiter
--region text AWS region (default: use boto3 defaults) Sentinel.UNSET
--endpoint-url text AWS endpoint URL (e.g., http://localhost:4566 for LocalStack) Sentinel.UNSET
--help boolean Show this message and exit. Sentinel.UNSET

zae-limiter resource

Resource-level default limit configuration.

Configure default limits for specific resources (e.g., gpt-4, claude-3). Resource defaults override system defaults but are overridden by entity limits.

Usage:

zae-limiter resource [OPTIONS] COMMAND [ARGS]...

Options:

Name Type Description Default
--help boolean Show this message and exit. Sentinel.UNSET

Subcommands

  • bypass: Bypass a resource: admit every request, debit nothing, keep counting.
  • clear-cascade: Clear a resource's cascade policy, reverting to inherit.
  • clear-disabled: Clear a resource's explicit disabled flag, reverting to inherit.
  • delete-defaults: Delete default limits for a resource.
  • disable: Disable a resource.
  • enable: Explicitly enable a resource.
  • get-defaults: Get default limits for a resource.
  • list: List all resources with configured defaults.
  • set-cascade: Set whether entities cascade to their parent on a resource.
  • set-defaults: Set default limits for a resource.
zae-limiter resource bypass

Bypass a resource: admit every request, debit nothing, keep counting.

RESOURCE_NAME is the resource to bypass (e.g., 'gpt-4').

Consumption is still counted in usage snapshots; only the reserved wcu limit still gates. Entities with their own explicit value (disable or enable) keep it. Lift it with resource clear-disabled. Needs the stack's Lambdas at 0.17.0 or later.

Examples:

zae-limiter resource bypass gpt-4

Usage:

zae-limiter resource bypass [OPTIONS] RESOURCE_NAME

Options:

Name Type Description Default
--name, -n text Stack identifier used as the CloudFormation stack name. zae-limiter
--region text AWS region (default: use boto3 defaults) Sentinel.UNSET
--endpoint-url text AWS endpoint URL (e.g., http://localhost:4566 for LocalStack) Sentinel.UNSET
--namespace, -N text Namespace within the table (default: "default") default
--help boolean Show this message and exit. Sentinel.UNSET
zae-limiter resource clear-cascade

Clear a resource's cascade policy, reverting to inherit.

RESOURCE_NAME is the resource to clear (e.g., 'llm'). Entities then cascade per their own policy, or per the flag they were created with.

Examples:

zae-limiter resource clear-cascade llm

Usage:

zae-limiter resource clear-cascade [OPTIONS] RESOURCE_NAME

Options:

Name Type Description Default
--name, -n text Stack identifier used as the CloudFormation stack name. zae-limiter
--region text AWS region (default: use boto3 defaults) Sentinel.UNSET
--endpoint-url text AWS endpoint URL (e.g., http://localhost:4566 for LocalStack) Sentinel.UNSET
--namespace, -N text Namespace within the table (default: "default") default
--help boolean Show this message and exit. Sentinel.UNSET
zae-limiter resource clear-disabled

Clear a resource's explicit disabled flag, reverting to inherit.

RESOURCE_NAME is the resource to clear (e.g., 'gpt-4'). Removes any explicit disable/enable value, so the resource resolves whatever it would inherit (currently always enabled, since there is no system-level disable).

Examples:

zae-limiter resource clear-disabled gpt-4

Usage:

zae-limiter resource clear-disabled [OPTIONS] RESOURCE_NAME

Options:

Name Type Description Default
--name, -n text Stack identifier used as the CloudFormation stack name. zae-limiter
--region text AWS region (default: use boto3 defaults) Sentinel.UNSET
--endpoint-url text AWS endpoint URL (e.g., http://localhost:4566 for LocalStack) Sentinel.UNSET
--namespace, -N text Namespace within the table (default: "default") default
--help boolean Show this message and exit. Sentinel.UNSET
zae-limiter resource delete-defaults

Delete default limits for a resource.

RESOURCE_NAME is the resource to delete defaults from (e.g., 'gpt-4', 'claude-3').

Examples:

# Delete with confirmation prompt
zae-limiter resource delete-defaults gpt-4

# Skip confirmation
zae-limiter resource delete-defaults gpt-4 --yes

Usage:

zae-limiter resource delete-defaults [OPTIONS] RESOURCE_NAME

Options:

Name Type Description Default
--name, -n text Stack identifier used as the CloudFormation stack name. zae-limiter
--region text AWS region (default: use boto3 defaults) Sentinel.UNSET
--endpoint-url text AWS endpoint URL (e.g., http://localhost:4566 for LocalStack) Sentinel.UNSET
--yes, -y boolean Skip confirmation prompt Sentinel.UNSET
--namespace, -N text Namespace within the table (default: "default") default
--help boolean Show this message and exit. Sentinel.UNSET
zae-limiter resource disable

Disable a resource.

RESOURCE_NAME is the resource to disable (e.g., 'gpt-4').

Existing buckets are stamped immediately, so the change takes effect on the next request. Entities with an explicit enable override keep their access.

Examples:

zae-limiter resource disable gpt-4

Usage:

zae-limiter resource disable [OPTIONS] RESOURCE_NAME

Options:

Name Type Description Default
--name, -n text Stack identifier used as the CloudFormation stack name. zae-limiter
--region text AWS region (default: use boto3 defaults) Sentinel.UNSET
--endpoint-url text AWS endpoint URL (e.g., http://localhost:4566 for LocalStack) Sentinel.UNSET
--namespace, -N text Namespace within the table (default: "default") default
--help boolean Show this message and exit. Sentinel.UNSET
zae-limiter resource enable

Explicitly enable a resource.

RESOURCE_NAME is the resource to enable (e.g., 'gpt-4'). Stores an explicit disabled: false at the resource level, which is the same value the resource resolves to when nothing sets it; use clear-disabled to go back to inheriting instead. There is no system-level disable.

Examples:

zae-limiter resource enable gpt-4

Usage:

zae-limiter resource enable [OPTIONS] RESOURCE_NAME

Options:

Name Type Description Default
--name, -n text Stack identifier used as the CloudFormation stack name. zae-limiter
--region text AWS region (default: use boto3 defaults) Sentinel.UNSET
--endpoint-url text AWS endpoint URL (e.g., http://localhost:4566 for LocalStack) Sentinel.UNSET
--namespace, -N text Namespace within the table (default: "default") default
--help boolean Show this message and exit. Sentinel.UNSET
zae-limiter resource get-defaults

Get default limits for a resource.

RESOURCE_NAME is the resource to query (e.g., 'gpt-4', 'claude-3').

Examples:

zae-limiter resource get-defaults gpt-4
zae-limiter resource get-defaults claude-3 --name prod

Sample Output:

Defaults for resource 'gpt-4':
  rpm: 500/min
  tpm: 50000/min

Usage:

zae-limiter resource get-defaults [OPTIONS] RESOURCE_NAME

Options:

Name Type Description Default
--name, -n text Stack identifier used as the CloudFormation stack name. zae-limiter
--region text AWS region (default: use boto3 defaults) Sentinel.UNSET
--endpoint-url text AWS endpoint URL (e.g., http://localhost:4566 for LocalStack) Sentinel.UNSET
--namespace, -N text Namespace within the table (default: "default") default
--help boolean Show this message and exit. Sentinel.UNSET
zae-limiter resource list

List all resources with configured defaults.

Examples:

zae-limiter resource list
zae-limiter resource list --name prod

Sample Output:

Resources with configured defaults:
  gpt-4
  gpt-3.5-turbo
  claude-3

Usage:

zae-limiter resource list [OPTIONS]

Options:

Name Type Description Default
--name, -n text Stack identifier used as the CloudFormation stack name. zae-limiter
--region text AWS region (default: use boto3 defaults) Sentinel.UNSET
--endpoint-url text AWS endpoint URL (e.g., http://localhost:4566 for LocalStack) Sentinel.UNSET
--namespace, -N text Namespace within the table (default: "default") default
--help boolean Show this message and exit. Sentinel.UNSET
zae-limiter resource set-cascade

Set whether entities cascade to their parent on a resource.

RESOURCE_NAME is the resource (e.g., 'gpt-4'); VALUE is 'on' or 'off'. An entity's own policy for the resource (or its entity-wide one) still wins. Existing buckets are restamped immediately. Requires a stack whose Lambdas are 0.16.0 or later (run 'zae-limiter upgrade' first if not).

Examples:

zae-limiter resource set-cascade gpt-4 on
zae-limiter resource set-cascade llm off

Usage:

zae-limiter resource set-cascade [OPTIONS] RESOURCE_NAME {on|off}

Options:

Name Type Description Default
--name, -n text Stack identifier used as the CloudFormation stack name. zae-limiter
--region text AWS region (default: use boto3 defaults) Sentinel.UNSET
--endpoint-url text AWS endpoint URL (e.g., http://localhost:4566 for LocalStack) Sentinel.UNSET
--namespace, -N text Namespace within the table (default: "default") default
--help boolean Show this message and exit. Sentinel.UNSET
zae-limiter resource set-defaults

Set default limits for a resource.

RESOURCE_NAME is the resource to configure (e.g., 'gpt-4', 'claude-3'). Resource defaults override system defaults for this specific resource.

Examples:

# Set TPM and RPM defaults for gpt-4
zae-limiter resource set-defaults gpt-4 -l tpm:100000 -l rpm:1000

# Set limits with explicit period
zae-limiter resource set-defaults gpt-4 -l rpm:1000/min -l tph:50000/hour

Usage:

zae-limiter resource set-defaults [OPTIONS] RESOURCE_NAME

Options:

Name Type Description Default
--name, -n text Stack identifier used as the CloudFormation stack name. zae-limiter
--region text AWS region (default: use boto3 defaults) Sentinel.UNSET
--endpoint-url text AWS endpoint URL (e.g., http://localhost:4566 for LocalStack) Sentinel.UNSET
--limit, -l text Limit in 'name:rate[/period]' or 'name:rate[/period]:burst' format (repeatable). Period: /sec, /min (default), /hour, /day. Sentinel.UNSET
--soft text Make the named limit soft: metered and debited, but never a reason to reject (repeatable). Must name a limit given with -l. Sentinel.UNSET
--namespace, -N text Namespace within the table (default: "default") default
--help boolean Show this message and exit. Sentinel.UNSET

zae-limiter status

Get comprehensive status of rate limiter infrastructure.

Shows connectivity, stack status, version compatibility, table metrics, and IAM role ARNs. Read-only operation - does not modify any resources.

Examples:

zae-limiter status --name my-app --region us-east-1
zae-limiter status --name dev --endpoint-url http://localhost:4566

Sample Output:

Status: my-app
==================================================

Connectivity
  Available:     ✓ Yes
  Latency:       42ms
  Region:        us-east-1

Infrastructure
  Stack:         CREATE_COMPLETE
  Table:         ACTIVE
  Aggregator:    Enabled
  Provisioner:   Enabled

Versions
  Client:        0.6.0
  Schema:        0.6.0
  Lambda:        0.6.0

Table Metrics
  Items:         1,234
  Size:          256 KB

✓ Infrastructure is ready

Usage:

zae-limiter status [OPTIONS]

Options:

Name Type Description Default
--name, -n text Resource identifier used as the CloudFormation stack name Sentinel.UNSET
--region text AWS region (default: use boto3 defaults) Sentinel.UNSET
--endpoint-url text AWS endpoint URL (e.g., http://localhost:4566 for LocalStack, or other AWS-compatible services) Sentinel.UNSET
--help boolean Show this message and exit. Sentinel.UNSET

zae-limiter system

System-level default limit configuration.

Configure global defaults that apply to ALL resources unless overridden. System defaults are the lowest priority in the hierarchy.

Usage:

zae-limiter system [OPTIONS] COMMAND [ARGS]...

Options:

Name Type Description Default
--help boolean Show this message and exit. Sentinel.UNSET

Subcommands

zae-limiter system delete-defaults

Delete all system-wide default limits and config.

Examples:

# Delete with confirmation prompt
zae-limiter system delete-defaults

# Skip confirmation
zae-limiter system delete-defaults --yes

Usage:

zae-limiter system delete-defaults [OPTIONS]

Options:

Name Type Description Default
--name, -n text Stack identifier used as the CloudFormation stack name. zae-limiter
--region text AWS region (default: use boto3 defaults) Sentinel.UNSET
--endpoint-url text AWS endpoint URL (e.g., http://localhost:4566 for LocalStack) Sentinel.UNSET
--yes, -y boolean Skip confirmation prompt Sentinel.UNSET
--namespace, -N text Namespace within the table (default: "default") default
--help boolean Show this message and exit. Sentinel.UNSET
zae-limiter system get-defaults

Get system-wide default limits and config.

Examples:

zae-limiter system get-defaults
zae-limiter system get-defaults --name prod

Sample Output:

System-wide defaults:
  Limits:
    rpm: 1000/min
    tpm: 100000/min
  on_unavailable: allow

Usage:

zae-limiter system get-defaults [OPTIONS]

Options:

Name Type Description Default
--name, -n text Stack identifier used as the CloudFormation stack name. zae-limiter
--region text AWS region (default: use boto3 defaults) Sentinel.UNSET
--endpoint-url text AWS endpoint URL (e.g., http://localhost:4566 for LocalStack) Sentinel.UNSET
--namespace, -N text Namespace within the table (default: "default") default
--help boolean Show this message and exit. Sentinel.UNSET
zae-limiter system set-defaults

Set system-wide default limits.

System defaults apply to ALL resources unless overridden at resource or entity level.

Examples:

# Set global defaults
zae-limiter system set-defaults -l tpm:10000 -l rpm:100

# Set defaults with unavailability behavior
zae-limiter system set-defaults -l tpm:10000 --on-unavailable allow

Usage:

zae-limiter system set-defaults [OPTIONS]

Options:

Name Type Description Default
--name, -n text Stack identifier used as the CloudFormation stack name. zae-limiter
--region text AWS region (default: use boto3 defaults) Sentinel.UNSET
--endpoint-url text AWS endpoint URL (e.g., http://localhost:4566 for LocalStack) Sentinel.UNSET
--limit, -l text Limit in 'name:rate[/period]' or 'name:rate[/period]:burst' format (repeatable). Period: /sec, /min (default), /hour, /day. Sentinel.UNSET
--soft text Make the named limit soft: metered and debited, but never a reason to reject (repeatable). Must name a limit given with -l. Sentinel.UNSET
--on-unavailable choice (allow | block) Behavior when DynamoDB is unavailable Sentinel.UNSET
--namespace, -N text Namespace within the table (default: "default") default
--help boolean Show this message and exit. Sentinel.UNSET

zae-limiter upgrade

Upgrade infrastructure to match client version.

Applies this version's CloudFormation template to the stack (IAM policies included), then updates Lambda code and version records to match the current client. The template goes through a change set, and a change that would replace or remove a resource is refused: nothing is applied and no code is pushed. Use --force to update even when versions already match, and --lambda-only to skip the template.

The stack's minimum client version is kept, never lowered, and a client below it is refused rather than allowed to downgrade the Lambdas.

Examples:

# Standard upgrade
zae-limiter upgrade --name my-app --region us-east-1

# Force Lambda update
zae-limiter upgrade --name my-app --force

Usage:

zae-limiter upgrade [OPTIONS]

Options:

Name Type Description Default
--name, -n text Resource identifier used as the CloudFormation stack name. zae-limiter
--region text AWS region (default: use boto3 defaults) Sentinel.UNSET
--endpoint-url text AWS endpoint URL (e.g., http://localhost:4566 for LocalStack, or other AWS-compatible services) Sentinel.UNSET
--lambda-only boolean Only update Lambda code; do not apply the stack template Sentinel.UNSET
--force boolean Force update even if version matches Sentinel.UNSET
--help boolean Show this message and exit. Sentinel.UNSET

zae-limiter usage

Usage snapshot commands.

Query historical usage data aggregated by the Lambda aggregator. Snapshots track token consumption per entity/resource in hourly and daily windows.

Usage:

zae-limiter usage [OPTIONS] COMMAND [ARGS]...

Options:

Name Type Description Default
--help boolean Show this message and exit. Sentinel.UNSET

Subcommands

  • list: List usage snapshots.
  • summary: Show aggregated usage summary.
zae-limiter usage list

List usage snapshots.

Query historical token consumption data. Requires either --entity-id or --resource. Use --plot for ASCII chart visualization.

Examples:

zae-limiter usage list --entity-id user-123
zae-limiter usage list --resource gpt-4 --window hourly
zae-limiter usage list --entity-id user-123 --plot

Note

Either --entity-id or --resource must be provided.

ASCII Charts

The --plot flag requires the optional plot extra: pip install 'zae-limiter[plot]'

Sample Output:

Usage Snapshots

Window Start          Type    Resource  Entity    Events  Counters
────────────────────  ──────  ────────  ────────  ──────  ────────────────
2026-01-15T10:00:00Z  hourly  gpt-4     user-123  42      tpm=15,000
2026-01-15T09:00:00Z  hourly  gpt-4     user-123  38      tpm=12,500

Total: 2 snapshots

Usage:

zae-limiter usage list [OPTIONS]

Options:

Name Type Description Default
--name, -n text Resource identifier used as the CloudFormation stack name. zae-limiter
--region text AWS region (default: use boto3 defaults) Sentinel.UNSET
--endpoint-url text AWS endpoint URL (e.g., http://localhost:4566 for LocalStack, or other AWS-compatible services) Sentinel.UNSET
--entity-id, -e text Entity ID to query (required unless --resource is provided) Sentinel.UNSET
--resource, -r text Resource name filter (required if --entity-id is not provided) Sentinel.UNSET
--window, -w choice (hourly | daily) Filter by window type Sentinel.UNSET
--start text Start time (ISO format, e.g., 2024-01-01T00:00:00Z) Sentinel.UNSET
--end text End time (ISO format, e.g., 2024-01-31T23:59:59Z) Sentinel.UNSET
--limit, -l integer Maximum number of snapshots to return (default: 100) 100
--plot, -p boolean Display as ASCII charts instead of table (requires: pip install 'zae-limiter[plot]') Sentinel.UNSET
--namespace, -N text Namespace within the table (default: "default") default
--help boolean Show this message and exit. Sentinel.UNSET
zae-limiter usage summary

Show aggregated usage summary.

Computes total and average consumption across matching snapshots. Useful for billing, reporting, and capacity planning.

Examples:

zae-limiter usage summary --entity-id user-123
zae-limiter usage summary --resource gpt-4 --window daily

Note

Either --entity-id or --resource must be provided.

Sample Output:

Usage Summary

Entity:     user-123
Resource:   gpt-4
Snapshots:  24
Time Range: 2026-01-14T00:00:00Z to 2026-01-15T23:00:00Z

Limit  Total     Average
─────  ────────  ─────────
rpm        950      39.58
tpm    450,000  18,750.00

Usage:

zae-limiter usage summary [OPTIONS]

Options:

Name Type Description Default
--name, -n text Resource identifier used as the CloudFormation stack name. zae-limiter
--region text AWS region (default: use boto3 defaults) Sentinel.UNSET
--endpoint-url text AWS endpoint URL (e.g., http://localhost:4566 for LocalStack, or other AWS-compatible services) Sentinel.UNSET
--entity-id, -e text Entity ID to query (required unless --resource is provided) Sentinel.UNSET
--resource, -r text Resource name filter (required if --entity-id is not provided) Sentinel.UNSET
--window, -w choice (hourly | daily) Filter by window type Sentinel.UNSET
--start text Start time (ISO format, e.g., 2024-01-01T00:00:00Z) Sentinel.UNSET
--end text End time (ISO format, e.g., 2024-01-31T23:59:59Z) Sentinel.UNSET
--namespace, -N text Namespace within the table (default: "default") default
--help boolean Show this message and exit. Sentinel.UNSET

zae-limiter version

Show infrastructure version information.

Displays client version, schema version, and deployed infrastructure versions. Checks compatibility between client and infrastructure. Read-only: reads the version record and reports; never updates the Lambda, deploys a stack, or registers a namespace.

Examples:

zae-limiter version --name my-app --region us-east-1
zae-limiter version --endpoint-url http://localhost:4566

Sample Output:

zae-limiter Infrastructure Version
====================================

Client Version:     0.6.0
Schema Version:     0.6.0

Infra Schema:       0.6.0
Lambda Version:     0.6.0
Min Client Version: 0.5.0

Status: COMPATIBLE

Usage:

zae-limiter version [OPTIONS]

Options:

Name Type Description Default
--name, -n text Resource identifier used as the CloudFormation stack name. zae-limiter
--region text AWS region (default: use boto3 defaults) Sentinel.UNSET
--endpoint-url text AWS endpoint URL (e.g., http://localhost:4566 for LocalStack, or other AWS-compatible services) Sentinel.UNSET
--help boolean Show this message and exit. Sentinel.UNSET

Environment Variables

The CLI respects standard AWS environment variables:

Variable Description
AWS_ACCESS_KEY_ID AWS access key
AWS_SECRET_ACCESS_KEY AWS secret key
AWS_SESSION_TOKEN AWS session token
AWS_DEFAULT_REGION Default AWS region
AWS_PROFILE AWS profile name
AWS_ENDPOINT_URL Custom endpoint URL

Exit Codes

Code Description
0 Success
1 General error
2 Invalid arguments
3 AWS API error
4 Stack not found

Namespace Flag

Most data-access commands accept --namespace / -N to scope operations to a specific namespace. When omitted, operations default to the "default" namespace.

Namespace registration

Commands that write (set-*, delete-*, entity create, disable / enable / clear-disabled, set-cascade / clear-cascade, entity set-parent, entity reset / entity top-up, limits apply) register the namespace if it does not exist yet. Commands that only read never do: they exit 1 and name the register command (see Read-Only Commands).

# Entity operations in a specific namespace
zae-limiter entity set-limits user-123 --namespace tenant-alpha -l rpm:1000

# System defaults for a namespace
zae-limiter system set-defaults --namespace tenant-alpha -l rpm:5000

# Usage and audit scoped to a namespace
zae-limiter usage list --namespace tenant-alpha
zae-limiter audit list --namespace tenant-alpha

Read-Only Commands

Commands that only read never change anything: they never deploy a stack, register a namespace, write the version record, or push Lambda code. When something they need is missing, they stop instead of creating it.

Command Reads
status, check, version, list Stack, table and version record
entity show, entity get-limits, entity list, entity list-resources One namespace
resource get-defaults, resource list, system get-defaults One namespace
audit list, usage list, usage summary One namespace
namespace list, namespace show, namespace orphans The namespace registry
limits plan, limits diff One namespace, through the provisioner Lambda

status, check and version report a missing stack or an out-of-date Lambda as part of their output. Every other read-only command stops with exit code 1:

Situation Message
Stack missing Error: Stack '<name>' not found in <region>. Deploy it with 'zae-limiter deploy -n <name>'.
Namespace missing Error: Namespace '<ns>' not found. Register it with 'zae-limiter namespace register <ns>'.
Client below the stack's minimum version Error: Version mismatch: ... Please upgrade.

Lambdas behind the client. A plain read does not use the Lambdas, so it runs normally and leaves them alone. limits plan and limits diff hand the manifest to the provisioner Lambda, so they require an up-to-date stack and refuse otherwise, before invoking it:

Error: the stack's Lambdas run 0.14.0; this client is 0.15.0. Run 'zae-limiter upgrade -n my-app' first, then re-run the plan.

A stack whose Lambda version is unknown (no version record, or one written by a client that deployed no Lambda code) is refused the same way, as run unknown.

Every other command intends to write and keeps its behaviour: deploy and upgrade provision and update, and the data commands that write register a missing namespace.

upgrade applies this version's CloudFormation template to an existing stack before it pushes Lambda code, so the stack's IAM policies match the client (deploy leaves an existing stack's template alone). Unlike the other writing commands it does not connect through Repository.open(): it never auto-updates the Lambdas on connect (that would push code before the template) and never provisions a missing stack. Its steps are the template, the Lambda code, the version record, then the stack tags; it reports "already up to date" when the template has nothing to change and the Lambdas already run this version. The template goes through a change set; a change that would replace or remove a resource is refused, nothing is applied, no code is pushed, and the command exits 1 naming each resource. --lambda-only skips the template. Run zae-limiter upgrade on each stack before rolling out v0.17.0 clients: their bucket writes need IAM actions the v0.16.0 policies lack.

Declarative Limits

The limits command group manages rate limits declaratively via YAML manifest files. Changes are applied through a Lambda provisioner that tracks managed state and computes diffs, similar to how terraform plan and terraform apply work.

YAML Manifest Format

Each level's limits replaces the levels below it. To reuse limits across levels without repeating them, see Reusing Limits with YAML Anchors.

namespace: default

system:
  on_unavailable: block
  limits:
    rpm:
      capacity: 1000
    tpm:
      capacity: 100000

resources:
  gpt-4:
    limits:
      rpm:
        capacity: 500
      tpm:
        capacity: 50000
  gpt-3.5-turbo:
    limits:
      rpm:
        capacity: 2000
      tpm:
        capacity: 500000

entities:
  user-premium:
    resources:
      gpt-4:
        limits:
          rpm:
            capacity: 1000
          tpm:
            capacity: 100000

Only capacity is required per limit. Defaults: refill_amount = capacity, refill_period = 60 seconds.

A limit may also carry a schedule, which changes its parameters while the current minute matches a cron pattern, and a reset_schedule, which restores the balance to the full allowance when a window opens:

limits:
  rpm:
    capacity: 1000
    schedule:
      - cron: "* 9-17 * * MON-FRI"
        tz: America/New_York
        scale: 0.5
      - cron: "* 0-6 * * *"
        tz: America/New_York
        capacity: 2000
  rpd:
    capacity: 10000
    reset_schedule:
      - cron: "0 0 * * *"
        tz: America/New_York

Both take standard 5-field cron. A schedule entry sets either scale or the absolute fields (capacity, refill_amount, refill_period_seconds); entries are checked in order and the first match wins. A reset_schedule entry takes cron and tz only.

A limit with a reset_schedule does not drip: refill_amount defaults to 0 rather than to capacity, and setting it to anything positive is rejected. A limit drips or resets, never both. Schedule and ResetSchedule round trip through the generated Custom::ZaeLimiterLimits resource.

A quota can instead reset a fixed time after each entity's own first use — a session quota. Give reset_after_seconds (a whole number of seconds) in place of reset_schedule; the two are mutually exclusive, and refill_amount again defaults to 0:

limits:
  session:
    capacity: 10000
    reset_after_seconds: 18000   # 5h from each entity's own first use

reset_after_seconds round trips through Custom::ZaeLimiterLimits as ResetAfterSeconds.

Soft Limits

Any limits.<name> mapping, at every level, may set soft: true: the limit is metered and debited but never rejects a request (Soft Limits and Bypass). Omitting it makes the limit hard — the manifest owns it like every other field of the limit.

resources:
  gpt-4:
    limits:
      rpm: {capacity: 500}
      tpm: {capacity: 50000, soft: true}

soft must be a boolean. It round trips through Custom::ZaeLimiterLimits as a Soft property on each limit. A resource- or system-level change of soft-ness restamps the existing buckets of that level on apply; a routine apply that changes none writes no buckets for it.

Cascade and Disabled

Entries under resources.<name> and entities.<id>.resources.<name> may also set two flags, each true, false, or omitted; disabled also takes bypass:

Field Meaning See
disabled Turn the resource off (or re-admit one entity); bypass admits without debiting Disabling Resources and Entities, Bypass
cascade Whether acquires on this resource also debit the parent Cascade Policy per Resource
resources:
  gpt-4:
    cascade: true
    limits:
      tpm: {capacity: 10000}
  llm:
    cascade: false
    limits:
      cost: {capacity: 500}
entities:
  org-acme:
    resources:
      gpt-4:
        limits:
          tpm: {capacity: 100000}
  • The manifest owns both flags for every item it declares. Omitting one clears a value set earlier by set-cascade, disable or the Python API on the next apply.
  • Neither applies to system. Either one there is an error, so plan, apply and diff fail before anything is written. Set them on resources.<name> or entities.<id>.resources.<name> instead.
  • cascade must be a boolean; a value like "yes" fails the plan.
  • Bucket restamps: disabled restamps every declared resource and entity level on each apply. cascade restamps only the levels whose stored policy actually changed, so a routine apply writes no buckets for it.
  • CloudFormation: both round trip through Custom::ZaeLimiterLimits as the Disabled and Cascade properties on Resources and Entities entries. Either one under System fails the stack operation.
  • Version: a manifest that sets cascade needs a stack whose Lambdas are 0.16.0 or later, and raises the stack's minimum client version to 0.16.0. One that sets soft: true or disabled: bypass needs 0.17.0 or later and raises the minimum to 0.17.0.
  • disabled must be true, false or bypass; CloudFormation also accepts "Bypass".

limits plan warns when a resource sets cascade: true and no entity in the manifest has its own limits for it, because parents would then be limited by the per-user resource defaults:

Warning: resources.gpt-4 sets cascade: true, but no entity in this manifest has its own limits for 'gpt-4', so parents will be limited by the per-user resource defaults

Preview Changes

# Show what would change (like terraform plan)
zae-limiter limits plan -n my-app -f limits.yaml

plan is read-only: it never deploys the stack, registers the manifest's namespace, or updates the Lambdas. It needs a deployed stack, a registered namespace and up-to-date Lambdas; if the Lambdas are behind this client, run zae-limiter upgrade -n my-app first (see Read-Only Commands). A manifest for a new namespace can be applied directly — limits apply registers it.

Output:

Plan: 4 change(s)

  + create system: (system defaults)
  + create resource: gpt-4
  + create resource: gpt-3.5-turbo
  + create entity: user-premium/gpt-4

Apply Changes

# Apply limits from YAML file
zae-limiter limits apply -n my-app -f limits.yaml

Output:

  + create system: (system defaults)
  + create resource: gpt-4
  + create resource: gpt-3.5-turbo
  + create entity: user-premium/gpt-4

Applied: 4 created, 0 updated, 0 deleted.

Subsequent applies with a modified YAML file will show ~ for updates and - for deletions (items removed from the manifest are deleted from DynamoDB).

Only entries that differ from what is stored are applied. The provisioner reads each declared config item first (one strongly consistent GetItem per entry, run concurrently) and skips any whose stored item is already identical — no write, no bucket fan-out. Adding one entry to a manifest of a thousand therefore writes one config item and fans out one entry:

  + create entity: user-1001/gpt-4

Applied: 1 created, 0 updated, 0 deleted (1000 unchanged).

Because the comparison is against the live table rather than the previous manifest, an entry changed out of band (for example with entity set-limits) still differs and is restored on the next apply. plan and diff make the same comparison, so they list only what an apply would change.

Pass --quiet / -q to plan, apply or diff to print only the summary line, without a line per changed entry. Errors are still printed.

Entries that declare disabled (kill switches and carve-outs, bypass included) are re-checked on every apply even when unchanged, so a bucket created while an earlier disable was being applied is still stamped. Limit changes are not re-checked: a bucket whose limits were changed out of band while its config entry still matches the manifest is not repaired by a plain apply. limits apply --full rewrites every declared entry and pushes its limits to existing buckets again, as every apply did before change-only applies. A change to soft alone, or to disabled: bypass alone, is a change like any other: it is written and fanned out.

An apply records every bucket fan-out it owes before it writes any config, and removes each one as soon as it lands. Every fan-out, an apply's own included, is run from what the table holds for that entry at that moment, not from the manifest being applied, so a stale or concurrent apply cannot undo a newer change. An apply that is interrupted (a Lambda timeout) or whose fan-out fails leaves only the unfinished ones, and a later apply retries exactly those, even when no entry changed:

  • one whose fan-out failed is retried by the very next apply;
  • one an interrupted apply left is retried once that apply is certainly gone: after the provisioner Lambda's timeout plus a minute. Until then a new apply leaves it alone, so it can never finish, or drop, work a still-running apply is doing.

An interrupted --full apply resumes where it stopped instead of starting again: the next --full apply retries only the unfinished fan-outs plus whatever the manifest changed, and prints Note: resumed the fan-outs an earlier full apply did not finish. Only work a --full apply left does that; any other unfinished fan-out never stops --full from fanning out every entry. plan and diff report what is waiting:

No config changes; 3 bucket fan-out(s) an earlier apply did not finish will be retried by the next apply.

Detect Drift

# Show drift between YAML and live DynamoDB state
zae-limiter limits diff -n my-app -f limits.yaml

diff is read-only with the same requirements as plan.

Output (when live state differs from YAML):

Drift detected: 1 difference(s)

  ~ resource: gpt-4

Generate CloudFormation Template

# Generate a CFN template with Custom::ZaeLimiterLimits resource
zae-limiter limits cfn-template -n my-app -f limits.yaml > limits-stack.yaml

# Deploy with AWS CLI
aws cloudformation deploy \
    --template-file limits-stack.yaml \
    --stack-name my-app-limits

The generated template uses Custom::ZaeLimiterLimits backed by the provisioner Lambda. The Lambda ARN is imported from the main stack via Fn::ImportValue.

A stack update applies only the entries that changed, like limits apply. Pass --full to emit FullApply: true on the resource, the stack's equivalent of limits apply --full. CloudFormation calls the resource only when a property changes, so adding FullApply is what runs the full apply; while it stays set, every update is a full one.

Common Options

Option Short Description
--name -n Stack identifier (required)
--file -f Path to YAML limits file (required)
--region AWS region
--endpoint-url Custom endpoint URL (e.g., LocalStack)
--namespace -N Namespace (default: "default")
--quiet -q Print only the summary, not a line per changed entry (plan, apply, diff)
--full Rewrite and fan out every declared entry, not only changed ones (apply); emit FullApply: true (cfn-template)

Partial Failures

Config writes are committed before the fan-out that carries them to live bucket items, so an apply can get part-way and stop. limits apply reports what landed, prints each failure on stderr, and exits 1:

Applied: 2 created, 1 updated, 0 deleted.

Errors (1):
  - bucket param sync entity user-123: <reason>

Every write is idempotent, so re-running the same manifest reconciles the remainder. Each fan-out an apply owes is recorded as its own pending item before the config is written, and removed only once it lands, so one that failed is retried by the next apply, and one cut short by a Lambda timeout by the first apply after that Lambda's timeout plus a minute, even when the manifest has not changed (unchanged entries are otherwise skipped). Two applies running at once cannot erase or take over each other's pending work: when both owe the same fan-out, it stays pending until each has finished its own. Right after a timeout, limits apply reports the fan-outs the timed-out run still holds with the same "No config changes; N bucket fan-out(s) …" line, not "up-to-date". The #PROVISIONER record is written either way, so it always describes the config that is actually in the table.

Provisioner Lambda

The plan, apply, and diff subcommands invoke the {name}-limits-provisioner Lambda function. This function must be deployed as part of the main stack before using these commands. It is deployed by default; zae-limiter deploy --no-provisioner (or --no-iam, which leaves no role for it) skips it.

Schedules and Quotas

system get-defaults, resource get-defaults and entity get-limits render a limit's schedule beneath it. Cron is shown canonically, with weekday and month as names, followed by the timezone and what the window does:

Limits for entity 'user-123' on resource 'gpt-4':
  rpm: 1,000/min
    Schedule:
      "* 9-17 * * MON-FRI" America/New_York  → scale 50%
      "* 0-6 * * *" America/New_York  → capacity 2,000

A quota carries its whole allowance and the instant it comes back on one line:

Limits for entity 'user-123' on resource 'gpt-4':
  session: 500 quota (resets "0 */5 * * *" America/New_York)
  rpmo: 1,000,000 quota (resets "0 0 1 * *" America/New_York)

A session quota names its window length and says "after first use", so it is not mistaken for a clock-aligned period:

Limits for entity 'user-123' on resource 'claude-sonnet':
  session: 10,000 quota (resets 5h after first use)

Schedules and session windows are set through the Python API or a YAML manifest. The -l name:rate/period flag on set-defaults and set-limits takes neither a cron expression nor a reset_after window.

-l replaces the whole level

A set writes the level's limits in full, and a limit built from -l carries no schedule and no session window. Running entity set-limits user-123 -r gpt-4 -l rpm:1000 against a level whose stored rpm is scheduled therefore drops that schedule, and a stored quota — calendar or session — becomes a dripping limit. Edit such levels through limits apply or the Python API.

Disabling Resources and Entities

The resource and entity command groups include disable, enable, and clear-disabled subcommands for turning access off without deleting stored limits. See ADR-125 for the full design.

Disabling is eager: existing buckets are stamped immediately, so the change takes effect on the very next request — no cache TTL or refill delay to wait out. acquire() raises a distinct ResourceDisabled exception (not RateLimitExceeded) for a disabled resource or entity; map it to HTTP 403, not 429, since retrying will not help.

# Turn off a resource for everyone without an entity-level override
zae-limiter resource disable gpt-4

# Explicitly enable a resource that is disabled by default
zae-limiter resource enable gpt-4

# Revert a resource to inheriting the disabled state
zae-limiter resource clear-disabled gpt-4
# Disable an entity across all resources
zae-limiter entity disable user-123

# Disable an entity for a specific resource only
zae-limiter entity disable user-123 --resource gpt-4

# Re-admit an entity to a resource that is disabled for everyone else
zae-limiter entity enable user-123 --resource gpt-4

# Revert an entity to inheriting the resource's disabled state
zae-limiter entity clear-disabled user-123 --resource gpt-4

An entity-level disabled: false override always wins, even when the resource is disabled for everyone else — resolution walks entity (resource-specific) → entity (_default_) → resource, and the first level with an explicit value wins regardless of which level supplies the limits. There is no system-level disable.

resource get-defaults and entity get-limits report that level's own explicit disabled value when it has one — not the fully resolved state across the entity → resource walk. A resource showing no Status: line can still be effectively disabled for a given entity because some other level in the walk sets it; use resolve_disabled() (see Resource or Entity Disabled) to get the actual resolved outcome for a specific entity+resource pair.

Defaults for resource 'gpt-4':
  rpm: 500/min
Status: DISABLED
Limits for entity 'user-123' on resource 'gpt-4':
  rpm: 1000/min
Status: enabled (explicit override)

No Status: line is printed when the level has no explicit disabled value (i.e. it inherits from elsewhere in the resolution walk). A level set to bypass prints Status: BYPASSED (see Bypass).

Soft Limits

system set-defaults, resource set-defaults and entity set-limits take a repeatable --soft NAME, which makes the named -l limit soft: metered and debited, but never a reason to reject. See Soft Limits and Bypass.

# Hard rpm, soft (metered-only) tpm
zae-limiter resource set-defaults gpt-4 -l rpm:500 -l tpm:50000 --soft tpm

--soft must name a limit given with -l. A set is a full replace, so a set-* without --soft tpm turns a soft tpm hard again. get-defaults and get-limits mark a soft limit (soft):

Defaults for resource 'gpt-4':
  rpm: 500/min
  tpm: 50,000/min (soft)

Bypass

resource bypass and entity bypass admit every request without debiting any limit, while still counting consumption; only the reserved wcu write limit still gates. Bypass is the third value of disabled, so it resolves by the same walk and is lifted with clear-disabled.

zae-limiter resource bypass gpt-4
zae-limiter entity bypass vip-1                   # every resource
zae-limiter entity bypass vip-1 --resource gpt-4  # one resource

zae-limiter resource clear-disabled gpt-4         # lift it

get-defaults and get-limits print Status: BYPASSED for a level that sets it. Storing a soft limit or a bypass needs a stack whose Lambdas are 0.17.0 or later and raises the stack's minimum client version to 0.17.0.

Cascade Policy per Resource

set-cascade and clear-cascade on the resource and entity groups decide, per resource, whether an entity's acquires also debit its parent. Use it when one entity needs different answers on different resources — for example, model limits that count against the org while a shared budget stays per user. See ADR-146.

# Model limits cascade to the parent; the shared budget does not
zae-limiter resource set-cascade gpt-4 on
zae-limiter resource set-cascade llm off

# One entity: on for one resource, or off for every resource without its own policy
zae-limiter entity set-cascade user-123 on --resource gpt-4
zae-limiter entity set-cascade user-123 off

# Revert to inheriting
zae-limiter resource clear-cascade llm
zae-limiter entity clear-cascade user-123 --resource gpt-4

The policy resolves like disabled: entity (resource-specific) → entity (_default_) → resource, first explicit value wins. When no level sets it, the entity's own cascade flag from entity create --cascade applies, so stacks that never set a policy behave as before. An entity with no parent never cascades.

Like disabling, a change is eager: existing buckets are restamped immediately. Setting or clearing a policy needs a stack whose Lambdas are 0.16.0 or later — otherwise the command exits 1 and names zae-limiter upgrade (or zae-limiter deploy, when the stack has no version record) — and raises the stack's minimum client version to 0.16.0.

resource get-defaults and entity get-limits print Cascade: on (explicit) or Cascade: off (explicit) when that level sets a policy, and nothing when it inherits.

Reset and Top-Up

entity reset and entity top-up change an entity's balance on one resource now, on every shard, without touching its configuration. Use them for a plan upgrade, a purchase of more allowance, or a support action that gives a user their allowance back. See ADR-149 and the Reset and Top-Up guide.

# Give user-123 its whole gpt-4 allowance back
zae-limiter entity reset user-123 --resource gpt-4

# Reset only the session quota
zae-limiter entity reset user-123 -r claude --limit session

# A purchase: 5,000 more session tokens, this period only
zae-limiter entity top-up user-123 -r claude --add session:5000

# A plan upgrade from 10,000 to 25,000 a day: new plan, then the difference
zae-limiter entity set-limits user-123 -r claude -l ...
zae-limiter entity top-up user-123 -r claude --add daily:15000
Command Option Meaning
entity reset ID --resource/-r (required) The resource to reset, one at a time
--limit/-l (repeatable) Limits to reset; omit for every limit on the resource
entity top-up ID --resource/-r (required) The resource to top up
--add/-a LIMIT:N (repeatable, required) Add N whole tokens to LIMIT; repeats add up
both --idempotency-key KEY Name the operation (1-64 of letters, digits, . _ : -); a retry with the same key within three days is applied once

Pass --idempotency-key when you may retry. Without one, an error leaves the outcome unknown: the command may have landed before it failed, and running it again may apply it twice.

What each does

Limit shape reset top-up --add L:N
Dripping (rpm, …) Back to its ceiling; debt forgiven At most the room below its ceiling (a refund). Less than asked is reported on stderr
Calendar quota Back to its share; a new period starts Exactly N, above the plan if need be, until the next reset
Session quota Its current window ends; the next request opens a fresh one at its full share (the balance is left for that request to restore) Exactly N until the window ends; with no live window, one opens now

Neither command touches the consumption counter, the disabled flag, configuration, the parent's buckets or other resources. A reset of an entity that has never acquired is a no-op; a quota top-up for one creates its bucket.

A top-up of a limit not yet on the bucket (configured after the bucket existed, never used since) exits 1 naming it. A quota top-up needs a stack whose Lambdas are 0.17.0 or later (an older aggregator would clamp the purchase away): otherwise the command exits 1 and names zae-limiter upgrade. The first top-up raises the stack's minimum client version to 0.17.0. A reset is not gated.

Moving an Entity to a New Parent

entity set-parent moves an entity under another parent, or makes it a root entity. Give exactly one of --parent or --none. See ADR-150.

# Move a user to another organisation
zae-limiter entity set-parent user-123 --parent org-b

# Make a user a root entity
zae-limiter entity set-parent user-123 --none
Moved entity 'user-123' from org-a to org-b (3 buckets stamped)

The move is eager, like a cascade policy change: the entity's buckets are restamped at once, and every process debits the new parent from its next acquire. Usage already charged to the old parent stays there, including by leases open across the move. Whether the entity debits its new parent follows its cascade policy, falling back to the --cascade flag it was created with, which the move does not change. A root entity created without --cascade and moved under a parent therefore does not cascade until you run entity set-cascade ID on.

The command refuses a parent that does not exist and a move that would make the entity its own ancestor, and exits 1 for either. If restamping stops part-way (throttling, for example), it exits 1 with the number of buckets restamped: the move itself landed, and re-running the same command finishes it. It needs a stack whose Lambdas are 0.17.0 or later and raises the stack's minimum client version to 0.17.0. Restart every client after upgrading, before the first move: a process that opened the stack with an older version keeps debiting the old parent until it reopens it.

Namespace Lifecycle

The namespace command group manages the namespace registry:

# Register namespaces
zae-limiter namespace register tenant-alpha tenant-beta

# List active namespaces
zae-limiter namespace list

# Show namespace details (including opaque ID)
zae-limiter namespace show tenant-alpha

# Soft delete (data preserved, forward lookup removed)
zae-limiter namespace delete tenant-alpha

# Recover a soft-deleted namespace
zae-limiter namespace recover <namespace-id>

# List deleted namespaces (candidates for purge)
zae-limiter namespace orphans

# Hard delete all data in a namespace (irreversible)
zae-limiter namespace purge <namespace-id> --yes