CLI Reference¶
Commands¶
zae-limiter¶
zae-limiter infrastructure management CLI.
Usage:
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:
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:
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:
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:
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:
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:
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:
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:
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:
Usage:
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:
Usage:
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:
Usage:
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:
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:
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:
Usage:
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:
Usage:
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:
Usage:
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:
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:
Sample Output:
Usage:
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:
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:
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:
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:
Usage:
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:
Sample Output:
Entity: user-123
Name: Alice Smith
Parent: org-456
Cascade: True
Created: 2026-01-15T10:30:00Z
Metadata: {'tier': 'premium'}
Usage:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
Usage:
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:
Usage:
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:
Usage:
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:
Data Loss
Purging permanently deletes all entities, buckets, configs, and audit logs in the namespace. This cannot be undone.
Usage:
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:
Usage:
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:
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:
Usage:
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:
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:
Usage:
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:
Usage:
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:
Usage:
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:
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:
Usage:
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:
Usage:
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:
Sample Output:
Usage:
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:
Sample Output:
Usage:
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:
Usage:
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:
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:
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:
Options:
| Name | Type | Description | Default |
|---|---|---|---|
--help |
boolean | Show this message and exit. | Sentinel.UNSET |
Subcommands
- delete-defaults: Delete all system-wide default limits and config.
- get-defaults: Get system-wide default limits and config.
- set-defaults: Set system-wide default limits.
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:
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:
Sample Output:
Usage:
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:
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:
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:
Options:
| Name | Type | Description | Default |
|---|---|---|---|
--help |
boolean | Show this message and exit. | Sentinel.UNSET |
Subcommands
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:
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:
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:
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:
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.
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,disableor the Python API on the nextapply. - Neither applies to
system. Either one there is an error, soplan,applyanddifffail before anything is written. Set them onresources.<name>orentities.<id>.resources.<name>instead. cascademust be a boolean; a value like"yes"fails the plan.- Bucket restamps:
disabledrestamps every declared resource and entity level on each apply.cascaderestamps only the levels whose stored policy actually changed, so a routine apply writes no buckets for it. - CloudFormation: both round trip through
Custom::ZaeLimiterLimitsas theDisabledandCascadeproperties onResourcesandEntitiesentries. Either one underSystemfails the stack operation. - Version: a manifest that sets
cascadeneeds a stack whose Lambdas are 0.16.0 or later, and raises the stack's minimum client version to 0.16.0. One that setssoft: trueordisabled: bypassneeds 0.17.0 or later and raises the minimum to 0.17.0. disabledmust betrue,falseorbypass; 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¶
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¶
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:
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¶
diff is read-only with the same requirements as plan.
Output (when live state differs from YAML):
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:
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.
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):
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
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