Libaws
Why
AWS is amazing, but it's hard to ship fast unless you're an expert.
I want to write down best practices as code, then forget about them so I can just ship.
I want to serve http, react to database writes, and use cron to schedule actions.
I want to push data S3 => EC2 => S3 with ephemeral Spot instances that live for seconds.
Did you know that EC2 is billed by the second, that Spot is 1/5 the price, and that Spot in Local Zones is 1/2 that price?
It's basically free. Oh and no egress fees between EC2 and S3 in the same region. Lambda's not the only thing that scales to zero. AWS is pretty awesome.
AWS should:
- Have fewer knobs
- Have sane defaults
- Be easy to use
- Be hard to screw up
- Be fast
- Be fun
- Have a tldr
It should be easy for a lambda to react to:
It should be easy to create:
How
Declare and deploy groups of related AWS infrastructure as infrastructure sets:
What
A simpler way to declare AWS infrastructure that is easy to use and extend.
There are two ways to use it:
The primary entrypoints are:
-
infra-ensure: deploy an infrastructure set.
libaws infra-ensure ./infra.yaml --preview
libaws infra-ensure ./infra.yaml
-
infra-ls: view infrastructure sets.
libaws infra-ls
-
infra-ensure --quick: quickly update Lambda code.
libaws infra-ensure ./infra.yaml --quick LAMBDA_NAME
-
infra-ensure --build-only / --from-build: build Lambda artifacts on one host, deploy them on another.
libaws infra-ensure ./infra.yaml --build-only ./build
libaws infra-ensure ./infra.yaml --from-build ./build
-
infra-rm: remove an infrastructure set.
libaws infra-rm ./infra.yaml --preview
libaws infra-rm ./infra.yaml
infra-ensure is a positive assertion. It asserts that some named infrastructure exists, and is configured correctly, creating or updating it if needed.
Other commands fall into two categories:
- Mutate AWS state:
ensure, new, and rm.
- View AWS state:
ls, get, scan, and describe.
Compared to the full AWS API, systems declared as infrastructure sets:
If you want to use the full AWS API, there are many great tools:
Readme Index
Install
CLI
go install github.com/nathants/libaws@latest
export PATH=$PATH:$(go env GOPATH)/bin
Go API
go get github.com/nathants/libaws@latest
TLDR
Define an Infrastructure Set
>> cd examples/simple/go/s3 && tree
.
├── infra.yaml
└── main.go
name: test-infraset-${uid}
s3:
test-bucket-${uid}:
attr:
- acl=private
lambda:
test-lambda-${uid}:
entrypoint: main.go
attr:
- memory=128
- timeout=60
policy:
- AWSLambdaBasicExecutionRole
trigger:
- type: s3
attr:
- test-bucket-${uid}
package main
import (
"context"
"fmt"
"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambda"
)
func handleRequest(_ context.Context, e events.S3Event) (events.APIGatewayProxyResponse, error) {
for _, record := range e.Records {
fmt.Println(record.S3.Object.Key)
}
return events.APIGatewayProxyResponse{StatusCode: 200}, nil
}
func main() {
lambda.Start(handleRequest)
}
Ensure the Infrastructure Set

View the Infrastructure Set
infra-ls lists the account. Select one exact set with --infraset NAME, or filter names with a positional substring; these selectors cannot be combined:
libaws infra-ls --infraset my-project
Depth-based colors by YAML

Trigger the Infrastructure Set

Quickly Update Lambda Code

Build and Deploy Lambda Artifacts Separately
Build Go Lambda artifacts once, then deploy them from the saved directory:
libaws infra-ensure ./infra.yaml --build-only ./build
libaws infra-ensure ./infra.yaml --from-build ./build
--build-only builds Go Lambdas without AWS access. Its manifest.json records each artifact's name, file, SHA-256 hash, and source checkout's commit and dirty state. --from-build verifies all selected artifacts before contacting AWS and deploys without source files or compilation. Both flags support --quick LAMBDA_NAME.
Python and container Lambdas use their normal deployment paths; Python code and dependencies are still packaged on the deployment host.
Delete the Infrastructure Set

Usage
Explore the CLI
libaws --help
Explore a CLI Entrypoint
libaws s3-ensure --help
For ec2-ssh, ec2-scp, ec2-rsync, and ec2-wait-ssh, -p/--preview only lists targets. Across the CLI, -p always means --preview; --private-ip, --profile, and --period have no short aliases.
ec2-rm-ami AMI_ID deregisters an owned AMI and asks EC2 to delete its associated snapshots, preserving snapshots used by other AMIs. --preview/-p lists verified backing snapshots as conditional deletions because sharing is checked at deletion time. Snapshot-deletion failures return an error even if deregistration succeeded; their snapshot IDs identify any remaining cleanup. An AMI ID that exists but is not owned by this account fails instead of being treated as absent.
Explore the Go API
Use editor completion, the API reference, or local documentation:
go doc github.com/nathants/libaws/lib
go doc github.com/nathants/libaws/lib.InfraListSet
Explore Simple Examples
- Alarm: go
- API: python, go, docker, custom domain
- DynamoDB: python, go, docker
- EC2: CLI with Spot/on-demand launches, VPC-selected or explicit subnets, and scoped SSH readiness pruning; AMI cleanup with shared-snapshot preservation.
- ECR: python, go, docker
- Function URL: go
- Includes: python, go
- S3: python, go, docker, R2 CLI
- Schedule: python, go, docker
- SES: go
- SQS: python, go, docker
- Websocket: python, go, docker
Explore Complex Examples
-
Coexisting infrastructure sets: exact-set inventory while an independent set is being removed.
-
Literal S3 keys: object/version CLI operations without path normalization.
-
DynamoDB failure retention: S3 retention with error, retained-event, delivery-failure, and stream-age alarms.
-
DynamoDB indexes: provisioned global indexes and local-index projections.
-
S3 append-only: append-only storage with separate writer and reader IAM users.
-
S3-EC2:
- Write to S3 in-bucket
- Which triggers Lambda
- Which launches EC2 Spot
- Which reads from in-bucket, writes to out-bucket, and terminates
Explore External Examples
Infrastructure Set
An infrastructure set is defined by YAML or Go struct and contains:
Typical Usage
-
Use infra-ensure to deploy an infrastructure set.
libaws infra-ensure ./infra.yaml --preview
libaws infra-ensure ./infra.yaml
-
Use infra-ls to view infrastructure sets.
libaws infra-ls
-
Use infra-ensure --quick LAMBDA_NAME to quickly update Lambda code.
libaws infra-ensure ./infra.yaml --quick LAMBDA_NAME
-
Use infra-rm to remove an infrastructure set.
libaws infra-rm ./infra.yaml --preview
libaws infra-rm ./infra.yaml
Design
-
There is no implicit coordination.
- If you aren't already serializing your infrastructure mutations, lock around DynamoDB.
-
No databases for infrastructure state. There are only two state locations:
-
AWS infrastructure is uniquely identified by name.
- All AWS infrastructure share a private namespace scoped to account/region. Use good names.
- Except S3, which shares a public namespace scoped to Earth. Use better names.
-
Mutative operations manipulate AWS state.
- Mutative operations are idempotent. If they fail due to a transient error, run them again.
- Mutative operations can
--preview. No output means no changes.
-
ensure are mutative operations that create or update infrastructure.
-
rm are mutative operations that delete infrastructure.
-
ls, get, scan, and describe operations are non-mutative.
-
Multiple infrastructure sets can be deployed into the same account/region.
Tradeoffs
-
ensure operations are positive assertions. They assert that some named infrastructure exists, and is configured correctly, creating or updating it if needed.
-
When possible, an existing same-named resource is automatically adopted and converged to the requested configuration.
-
Positive assertions CANNOT remove top-level infrastructure, but CAN remove configuration from them.
-
Removing a trigger, policy, or allow WILL remove that from the lambda.
-
Removing policy, or allow WILL remove that from the instance-profile.
-
Removing a security-group WILL remove that from the vpc.
-
Removing a rule WILL remove that from the security-group.
-
Removing an attr WILL remove that from a sqs, s3, dynamodb, or lambda.
-
Removing a keypair, vpc, instance-profile, sqs, s3, dynamodb, or lambda WON'T remove that from the account/region.
-
The operator decides IF and WHEN top-level infrastructure should be deleted, then uses an rm operation to do so.
-
As a convenience, infra-rm will remove ALL infrastructure CURRENTLY declared in an infra.yaml.
-
If a declared Lambda is already gone, infra-rm removes verifiably owned triggers and preserves ambiguous or independently owned resources.
-
When using ensure operations, no output means no changes.
-
For large infrastructure sets, this can mean a minute or two without output if no changes are needed.
-
To see a lot of output instead of none, set this environment variable:
export DEBUG=yes
-
Since ensure operations are idempotent, if you encounter errors like rate limits, just try again.
-
infra-ls is designed to list AWS accounts managed with infra-ensure. It will not work well in other scenarios.
infra.yaml
Use an infra.yaml file to declare an infrastructure set. The schema is as follows:
name: VALUE
lambda:
VALUE:
entrypoint: VALUE
policy: [VALUE ...]
allow: [VALUE ...]
attr: [VALUE ...]
require: [VALUE ...]
env: [VALUE ...]
include: [VALUE ...]
trigger:
- type: VALUE
attr: [VALUE ...]
s3:
VALUE:
attr: [VALUE ...]
user:
VALUE:
allow: [VALUE ...]
policy: [VALUE ...]
dynamodb:
VALUE:
key: [VALUE ...]
attr: [VALUE ...]
sqs:
VALUE:
attr: [VALUE ...]
vpc:
VALUE:
security-group:
VALUE:
rule: [VALUE ...]
keypair:
VALUE:
pubkey-content: VALUE
instance-profile:
VALUE:
allow: [VALUE ...]
policy: [VALUE ...]
Environment Variable Substitution
Anywhere in infra.yaml you can substitute environment variables from the caller's environment:
The following variables are defined during deployment, and are useful in allow declarations:
Name
Defines the name of the infrastructure set.
-
Schema:
name: VALUE
-
Example:
name: test-infraset
S3
Defines a S3 bucket:
-
The following attributes can be defined:
acl=VALUE, values: public | private, default: private
versioning=VALUE, values: true | false, default: false
appendonly=VALUE, values: true | false, default: false
metrics=VALUE, values: true | false, default: false
cors=VALUE, values: true | false, default: false
ttldays=VALUE, values: 0 | n, default: 0. Bucket-wide expiration in days.
allow_put=VALUE, values: $principal.amazonaws.com
-
Managed buckets require TLS, use SSE-S3 encryption, and reject SSE-C.
-
S3 CLI paths preserve literal keys, including dot segments and repeated slashes; s3-ls --quiet prints full bucket/key paths.
-
appendonly=true requires If-None-Match: * for object creation and multipart completion, denies deletion, and cannot be combined with expiration.
-
Setting cors=true uses * for allowed origins. To specify one or more explicit origins, do this instead:
corsorigin=http://localhost:8080
corsorigin=https://example.com
-
Bucket ACL can only be set at creation. Restore missing public-access-block settings before re-ensuring a bucket.
-
Schema:
s3:
VALUE:
attr:
- VALUE
-
Example:
s3:
test-bucket:
attr:
- versioning=true
- acl=public
IAM user
Defines an IAM user without creating credentials.
-
allow entries use SERVICE:ACTION RESOURCE.
-
policy entries name existing managed policies.
-
Undeclared inline and attached policies are removed.
-
Create the user's sole access key explicitly with libaws iam-ensure-user-api-key USER.
-
Schema:
user:
VALUE:
allow:
- SERVICE:ACTION RESOURCE
policy:
- VALUE
-
Example:
user:
backup-writer:
allow:
- s3:PutObject arn:aws:s3:::backup-bucket/*
DynamoDB
Defines a DynamoDB table:
-
Specify key as:
-
The following attributes can be defined:
read=VALUE, provisioned read capacity, default: 0
write=VALUE, provisioned write capacity, default: 0
ttl=ATTR_NAME, optional expiration attribute.
-
On global indices the following attributes can be defined:
projection=VALUE, projection type, default: ALL
read=VALUE, provisioned read capacity, default: 0
write=VALUE, provisioned write capacity, default: 0
-
On local indices the following attributes can be defined:
projection=VALUE, projection type, default: ALL
-
Schema:
dynamodb:
VALUE:
key:
- NAME:ATTR_TYPE:KEY_TYPE
attr:
- VALUE
global-index:
VALUE:
key:
- NAME:ATTR_TYPE:KEY_TYPE
non-key:
- NAME
attr:
- VALUE
local-index:
VALUE:
key:
- NAME:ATTR_TYPE:KEY_TYPE
non-key:
- NAME
attr:
- VALUE
-
Example:
dynamodb:
stream-table:
key:
- userid:s:hash
- timestamp:n:range
attr:
- stream=keys_only
auth-table:
key:
- id:s:hash
attr:
- write=50
- read=150
-
Example global secondary index:
dynamodb:
test-table:
key:
- id:s:hash
global-index:
test-index:
key:
- hometown:s:hash
-
Example local secondary index:
dynamodb:
test-table:
key:
- id:s:hash
- created:n:range
local-index:
test-index:
key:
- id:s:hash
- hometown:s:range
SQS
Defines a SQS queue:
-
The following attributes can be defined:
delay=VALUE, delay seconds, default: 0
size=VALUE, maximum message size bytes, default: 1048576
retention=VALUE, message retention period seconds, default: 345600
wait=VALUE, receive wait time seconds, default: 0
timeout=VALUE, visibility timeout seconds, default: 30
-
Schema:
sqs:
VALUE:
attr:
- VALUE
-
Example:
sqs:
test-queue:
attr:
- delay=20
- timeout=300
Keypair
Defines an EC2 keypair.
VPC
Defines a default-like VPC with an Internet Gateway and public access.
ec2-new --vpc NAME_OR_ID selects subnets in zones offering --type: all matching VPC subnets for --spot, or one at random for on-demand. Explicit --subnets "subnet-A subnet-B" overrides this selection.
Before --init, the first detected NVMe instance-store disk is formatted as whole-device ext4 and mounted at /mnt, writable by the login user. EBS disks are excluded. Existing partitions, signatures, device use, an occupied /mnt, or failed safety reads abort initialization. Without instance store, no disk changes are made. The mount is recorded by filesystem UUID.
-
Schema:
vpc:
VALUE: {}
-
Example:
vpc:
test-vpc: {}
Security Group
Defines a security group on a VPC.
Instance Profile
Defines an EC2 instance profile.
Lambda
Defines a Lambda.
Full ensure adds required IAM grants before deploying code and removes obsolete
grants after code activation and stream-destination updates succeed. IAM changes
can take time to propagate; defer permission removals if running invocations still
need them. --quick updates configuration and code only; deploy infrastructure
prerequisites first.
-
Schema:
lambda:
VALUE: {}
-
Example:
lambda:
test-lambda: {}
Entrypoint
Defines the code of the Lambda. It is one of:
-
A Python file.
-
A Go file. Libaws builds its complete package.
-
An ECR container URI ending in @sha256: followed by 64 lowercase hexadecimal characters.
-
Schema:
lambda:
VALUE:
entrypoint: VALUE
-
Example:
lambda:
test-lambda:
entrypoint: main.go
Attr
Defines Lambda attributes. The following can be defined:
-
concurrency=VALUE, reserved concurrency; omit for the unreserved pool or use 0 to disable the function.
-
memory=VALUE, RAM in megabytes, default: 128
-
timeout=VALUE, timeout in seconds, default: 300
-
logs-ttl-days=VALUE, CloudWatch Logs retention in days; 0 disables expiration, default: 7
-
Schema:
lambda:
VALUE:
attr:
- KEY=VALUE
-
Example:
lambda:
test-lambda:
attr:
- concurrency=100
- memory=256
- timeout=60
- logs-ttl-days=1
Policy
Defines policies on the Lambda's IAM role.
Allow
Defines allows on the Lambda's IAM role.
Env
Defines environment variables on the Lambda:
-
Names must match [a-zA-Z][a-zA-Z0-9_]+ and may not be repeated.
-
The environment JSON is limited to 4 KiB; the complete configuration update to 5 KiB.
-
Values may be empty and are preserved exactly.
-
Schema:
lambda:
VALUE:
env:
- KEY=VALUE
-
Example:
lambda:
test-lambda:
env:
- kind=production
Include
Defines extra content to include in the Lambda zip. Relative paths resolve beside infra.yaml:
-
This is ignored when entrypoint is an ECR container URI.
-
Schema:
lambda:
VALUE:
include:
- VALUE
-
Example:
lambda:
test-lambda:
include:
- ./cacerts.crt
- ../frontend/public/*
Require
Defines dependencies to install with pip in the virtualenv zip.
-
This is ignored unless the entrypoint is a Python file.
-
Relative paths, including -rrequirements.txt and local packages, resolve from the directory containing infra.yaml.
-
For source dependencies, add --build-constraint=build-requirements.txt with exact build-backend pins.
-
Schema:
lambda:
VALUE:
require:
- VALUE
-
Example:
lambda:
test-lambda:
require:
- fastapi==0.76.0
Trigger
Defines triggers for the Lambda:
Trigger Types
SES
Defines an SES email trigger.
-
Required attrs: dns=DOMAIN and bucket=BUCKET; optional: prefix=PREFIX.
-
Route53 and SES must already be configured for the domain, and the bucket must allow puts from SES.
-
The domain must be ASCII and at most 64 characters because it names the SES rule set.
-
Each infrastructure set may declare one SES trigger. Ensuring it replaces the active regional rule set.
-
Ensure rejects a same-named rule set containing other rules.
-
Schema:
lambda:
VALUE:
trigger:
- type: ses
attr:
- VALUE
-
Example:
s3:
my-bucket:
attr:
- allow_put=ses.amazonaws.com
lambda:
test-lambda:
trigger:
- type: ses
attr:
- dns=my-email-domain.com
- bucket=my-bucket
- prefix=emails/
API
Defines an API Gateway v2 HTTP API:
-
Add a custom domain with attr: domain=api.example.com. Inventory reports url=https://api.example.com; use api-url-domain NAME to obtain the DNS alias target for externally managed DNS.
-
Add a custom domain and update Route53 with attr: dns=api.example.com
-
Use dns=*.example.com to accept any subdomain
-
This domain, or its parent domain, must already exist as a hosted zone in Route53.
-
An exact or matching wildcard ACM certificate must already exist.
-
infra-rm removes exclusively managed domains and aliases; shared domains, routing-rule domains, hosted zones, and certificates remain.
-
Schema:
lambda:
VALUE:
trigger:
- type: api
attr:
- VALUE
-
Example:
lambda:
test-lambda:
trigger:
- type: api
attr:
- dns=api.example.com
URL
Defines a Lambda function URL trigger with streaming HTTP responses.
-
No attributes are required.
-
Schema:
lambda:
VALUE:
trigger:
- type: url
-
Example:
lambda:
test-lambda:
trigger:
- type: url
Websocket
Defines an API Gateway v2 websocket API:
-
infra-url-websocket infra.yaml NAME returns the default connection URL, wss://API_ID.execute-api.REGION.amazonaws.com/$default. The stage is required on the default endpoint, not on a custom-domain root mapping.
-
Add a custom domain with attr: domain=ws.example.com. Inventory reports url=wss://ws.example.com; use api-url-domain NAME to obtain the DNS alias target for externally managed DNS.
-
Add a custom domain and update Route53 with attr: dns=ws.example.com
-
This domain, or its parent domain, must already exist as a hosted zone in route53-ls.
-
An exact or matching wildcard ACM certificate must already exist.
-
infra-rm removes exclusively managed domains and aliases; shared domains, routing-rule domains, hosted zones, and certificates remain.
-
Schema:
lambda:
VALUE:
trigger:
- type: websocket
attr:
- VALUE
-
Example:
lambda:
test-lambda:
trigger:
- type: websocket
attr:
- dns=ws.example.com
S3
Defines an S3 trigger:
-
The only attribute must be a nonempty bucket name.
-
Object creation and deletion invoke the trigger.
-
Ensure rejects an existing conflicting notification instead of creating duplicate invocations.
-
Schema:
lambda:
VALUE:
trigger:
- type: s3
attr:
- VALUE
-
Example:
lambda:
test-lambda:
trigger:
- type: s3
attr:
- test-bucket
DynamoDB
Defines a DynamoDB trigger:
-
The first attribute must be the table name.
-
The following trigger attributes can be defined:
batch=VALUE, maximum batch size, default: 100
parallel=VALUE, parallelization factor, default: 1
retry=VALUE, maximum retry attempts, default: -1
window=VALUE, maximum batching window in seconds, default: 0
start=VALUE, required starting position: latest | trim_horizon; immutable on existing mappings.
on-failure=ARN, optional S3 bucket ARN for discarded invocation payloads.
metrics=event_count, enable Lambda event-source mapping EventCount metrics, default: disabled. Metric activation can lag behind mapping updates.
-
Handlers must return or raise an error to trigger retries; returning an HTTP-style error response counts as success. With retry=-1, Lambda retries until records expire from the stream after 24 hours.
-
The failure payload contains the keys and images selected by the table's stream attribute. Unread records that expire in DynamoDB cannot be retained.
-
Declare a private destination bucket and grant the execution role s3:PutObject on its objects and s3:ListBucket on the bucket. Keep it until failed records are reconciled; infra-rm deletes buckets in the removed set.
-
To prevent writes to a bucket recreated in another account, use an s3:ResourceAccount condition in a separately managed IAM policy.
-
Schema:
lambda:
VALUE:
trigger:
- type: dynamodb
attr:
- VALUE
-
Example:
lambda:
test-lambda:
trigger:
- type: dynamodb
attr:
- test-table
- start=trim_horizon
SQS
Defines a SQS trigger. Ensuring a declared trigger re-enables a disabled mapping:
-
The first attribute must be a nonempty queue name.
-
The following trigger attributes can be defined:
batch=VALUE, maximum batch size, default: 10
window=VALUE, maximum batching window in seconds, default: 0
-
Schema:
lambda:
VALUE:
trigger:
- type: sqs
attr:
- VALUE
-
Example:
lambda:
test-lambda:
trigger:
- type: sqs
attr:
- test-queue
Schedule
Defines a schedule trigger:
-
The only attribute must be the schedule expression.
-
Schema:
lambda:
VALUE:
trigger:
- type: schedule
attr:
- VALUE
-
Example:
lambda:
test-lambda:
trigger:
- type: schedule
attr:
- rate(24 hours)
ECR
Defines an ECR trigger:
-
Successful image actions from any ECR repository invoke the trigger; delivery is best-effort.
-
Schema:
lambda:
VALUE:
trigger:
- type: ecr
-
Example:
lambda:
test-lambda:
trigger:
- type: ecr
Alarm
Defines a CloudWatch alarm over Lambda metrics that invokes the declaring Lambda. The monitored Lambda may be a different function.
-
Required attributes:
name=VALUE, account-and-region-unique alarm name, 1–255 ASCII letters, digits, dots, hyphens, or underscores.
at-least=VALUE/minute, positive integer count threshold, maximum: 2147483647. For iterator age, use a positive duration in whole milliseconds, e.g. at-least=15m.
- Exactly one metric selector:
lambda-invocations=FUNCTION: Invocations, scoped to FunctionName.
lambda-errors=FUNCTION: Errors, scoped to FunctionName; no EventCount opt-in required.
lambda-retained-failures=FUNCTION: OnFailureDestinationDeliveredEventCount, scoped to EventSourceMappingUUID. Also requires dynamodb-table=TABLE, metrics=event_count, and an on-failure destination on that mapping. The function and table resolve the current mapping; re-ensure reconciles replacement mappings.
lambda-destination-delivery-failures=FUNCTION: DestinationDeliveryFailures, scoped to FunctionName, not one table or mapping. Counts failed destination-delivery attempts, including asynchronous invocation destinations; no EventCount opt-in required.
lambda-iterator-age=FUNCTION: IteratorAge, scoped to FunctionName, not one table or mapping. No EventCount opt-in required.
-
Evaluation uses AWS/Lambda and one 60-second period: Sum for counts, Maximum for iterator age. Age thresholds are converted to milliseconds. Missing data does not breach.
-
Errors counts failed invocations, including failed retries, not unique records. Throttled requests are excluded.
-
Retained-failure counts measure records, not batches; delivery does not mean they have been replayed or repaired. DroppedEventCount excludes successful on-failure deliveries and records expired by the source's retention limit.
-
IteratorAge measures the age of the last record when a batch is sent to the function, not a continuously running backlog clock. A disabled or stalled consumer can stop emitting useful data. A 15m threshold warns well before DynamoDB's 24-hour retention limit while processing continues.
-
Notifications occur on transitions into ALARM, not once per failed batch. Sending the alarm to the same unavailable or throttled Lambda can delay notification.
-
Schema:
lambda:
VALUE:
trigger:
- type: alarm
attr:
- name=VALUE
- lambda-invocations=VALUE
- at-least=VALUE/minute
-
Example:
lambda:
alert-handler:
trigger:
- type: alarm
attr:
- name=beta-invocations-runaway
- lambda-invocations=beta
- at-least=300/minute
- type: alarm
attr:
- name=beta-errors
- lambda-errors=beta
- at-least=1/minute
- type: alarm
attr:
- name=beta-retained-failures
- lambda-retained-failures=beta
- dynamodb-table=events
- at-least=1/minute
- type: alarm
attr:
- name=beta-retention-delivery-failed
- lambda-destination-delivery-failures=beta
- at-least=1/minute
- type: alarm
attr:
- name=beta-stream-age
- lambda-iterator-age=beta
- at-least=15m
Bash Completion
source completions.d/libaws.sh
Extending
Drop down to the AWS Go SDK and implement what you need.
Extend an existing mutative operation or add a new one.
- Make sure that mutative operations are IDEMPOTENT and can be PREVIEWED.
You will find examples in cmd/ and lib/ that can provide a good place to start.
You can reuse many existing operations like:
Alternatively, lift and shift to other infrastructure automation tooling. ls and describe operations will give you all the information you need.
Testing
Tests require Go 1.27+, Python 3.12+, uv, Node 22+ with pnpm, rootless Docker, and libcheck on PATH. Use scratch-account credentials and a permanent, publicly delegated Route53 zone in that account:
export LIBAWS_TEST_ACCOUNT=$ACCOUNT_NUM
export LIBAWS_TEST_DOMAIN=scratch.example.com
make test
Set LIBAWS_TEST_JOBS to change concurrency (default: 4; 1 for sequential runs). Do not overlap live suites in one account.
DNS/domain tests leave the supplied zone, a regional wildcard ACM certificate and its validation record, and the acm-fixture.${LIBAWS_TEST_DOMAIN} API Gateway domain in place. The unmapped domain keeps the certificate eligible for renewal and has no DNS record.
R2 tests are opt-in: set LIBAWS_R2_TEST_ACCOUNT to your R2_ACCOUNT_ID and supply R2_ACCESS_KEY_ID and R2_ACCESS_KEY_SECRET. They create and remove unique libaws-testing-* buckets.
Run one example with:
make
export PATH="$PWD:$PATH"
cd examples/simple/python/api
uv run --locked python -u test.py