add
Provision modular Day-2 cloud primitives without writing Terraform, configuring IAM policies, or opening the AWS Management Console.
What it does
Section titled “What it does”storage:s3creates a private S3 bucket (encrypted, CloudFront OAC, CORS ready for presigned browser uploads) and injectsS3_BUCKET_NAMEandS3_CDN_URLinto your container.db:dynamodbcreates aPAY_PER_REQUESTDynamoDB table (no fixed hourly instance cost) with Point-in-Time Recovery, a free VPC Gateway Endpoint, and injectsDYNAMODB_TABLE_NAMEinto your container.db:redisprovisions a cost-optimized ElastiCache for Valkey 8.0 node (Redis-protocol compatible) isolated in your VPC, reachable only from your ECS tasks or Lambda function, and injectsREDIS_URLinto your container.queue:sqscreates an SQS queue with long polling and a Dead-Letter Queue, and injectsSQS_QUEUE_URLandSQS_DLQ_URLinto your container. If your project has a background worker service, it also wires scale-to-zero auto-scaling driven by queue depth. On--target lambdaprojects the queue ships without a consumer (no worker service exists) — poll from function code or wire an event source mapping yourself.ai:bedrockgrants your container least-privilege permission to invoke Amazon Bedrock foundation models (no static AWS keys) and injectsBEDROCK_MODEL_IDinto your container. Run it interactively to pick a provider and model from the catalog, or pass--model <id>directly.email:sesprovisions Amazon SES for transactional email: a domain identity, DKIM signing, amail.subdomain for bounce handling with SPF, a DMARC baseline, least-privilegeses:SendEmailpermissions locked to your sender domain, andSES_FROM_EMAIL/SES_REGIONin your container. With--zone-idit creates the verification, DKIM, MX, SPF, and DMARC records in Route 53 automatically; otherwise it outputs the records to add at your DNS provider. If you already randomain add, the domain (and zone) is picked up automatically. The identity, DKIM, MAIL FROM, and DNS records are scoped to the production workspace as account-wide singletons, so PR previews never duplicate or delete them — preview containers inherit sending permission through their own task role.croncreates an EventBridge Scheduler schedule that runs a one-off Fargate task from your app’s task definition on acron(...)orrate(...)expression, with least-privilegeecs:RunTask+iam:PassRolepermissions. One schedule per project:--namecustomizes it, and re-running with--forcereplaces it in place. On--target lambdaprojects the schedule invokes the function directly with a JSON payload carrying the command — handle scheduled events in application code.- Every addon attaches least-privilege IAM policies to your task role, so your application code can use the AWS SDK with no extra configuration.
- Addon files live in
terraform/(s3.tf,dynamodb.tf,redis.tf,sqs.tf,bedrock.tf,ses.tf,cron.tf), sodestroytears them down andejectkeeps them automatically. PR-preview workspaces get isolated per-workspace resources. If your project has aworker.tfbackground service, addon environment variables are injected there too. - On
--target staticprojects addon infrastructure still scaffolds (queues, tables, buckets, identities), but container env injection is skipped — there is no task role to inject into. Read the resource names from the generated.tffiles and wire them into your build manually. - Emits an
add_runtelemetry event recording the capability and outcome.
Bedrock model access: AWS requires you to enable model access in the Bedrock console before your first
InvokeModelcall — including in the regions behind yourus.*cross-region inference profile. IAM permissions alone are not enough. Anthropic models additionally require a one-time First Time Use (FTU) form in the Bedrock console.
SES sandbox: new AWS accounts start in the SES sandbox and can only send to verified addresses. Request production access in the SES console (a short use-case form, usually approved within a day) before sending to real users.
npx grada-run add storage:s3npx grada-run add db:dynamodbnpx grada-run add db:dynamodb --partition-key userIdnpx grada-run add db:redisnpx grada-run add queue:sqsnpx grada-run add ai:bedrocknpx grada-run add ai:bedrock --model us.anthropic.claude-haiku-4-5-20251001-v1:0npx grada-run add ai:bedrock --list-modelsnpx grada-run add ai:bedrock --refreshnpx grada-run add email:ses --domain example.comnpx grada-run add email:ses --domain example.com --zone-id Z1234567890ABCnpx grada-run add cron --schedule "cron(0 2 * * ? *)" --cmd "npm run cron"npx grada-run add storage:s3 --forceAfter adding, run grada apply (or commit and push to trigger CI) to provision the resource.
To switch Bedrock models later, just run grada add ai:bedrock again (interactively) or with a new --model <id> — the model reference updates in place across bedrock.tf, main.tf, and worker.tf without needing --force.
| Flag | Description |
|---|---|
--region <region> |
Explicit AWS region override. |
--project-name <name> |
Explicit project name override (defaults to the name in terraform/main.tf, then the directory name). |
--partition-key <key> |
DynamoDB partition key name (default id). Letters, numbers, underscore, hyphen, and dot only. Only applies to db:dynamodb. |
--model <id> |
Bedrock model or inference profile ID (default us.anthropic.claude-sonnet-4-6). Only applies to ai:bedrock. |
--list-models |
Print the Bedrock model catalog (works offline, no project required). Only applies to ai:bedrock. |
--refresh |
Refresh the Bedrock model catalog from live AWS data before listing or provisioning. Only applies to ai:bedrock. |
--domain <domain> |
Domain for the SES identity (defaults to your domain add domain, or prompts interactively; required in --headless mode without a domain.tf). Only applies to email:ses. |
--from-email <email> |
Default sender address (default noreply@<domain>). Must belong to the SES domain. Only applies to email:ses. |
--zone-id <id> |
Route 53 hosted zone ID for automatic DKIM/SPF/DMARC records. Only applies to email:ses. |
--schedule <expr> |
EventBridge Scheduler expression, e.g. cron(0 2 * * ? *) or rate(1 hour) (default cron(0 0 * * ? *)). Only applies to cron. |
--cmd <command> |
Command to run inside the scheduled container (default npm run cron; also accepts --cron-command). Only applies to cron. |
--name <job> |
Job slug customizing the schedule name (default daily-job). Only applies to cron. |
--timezone <tz> |
IANA timezone for the schedule expression (default UTC). Only applies to cron. |
--force |
Overwrite the existing addon file (also accepts --force=false). Without it, re-adding refuses to clobber your edits. |
--headless |
Scaffold without interactive prompts, using flag values and built-in defaults (Bedrock default model, daily cron schedule). |
Requires a project initialized with grada (terraform/main.tf must exist).
Cost & Billing Drivers
Section titled “Cost & Billing Drivers”storage:s3: $0/mo fixed baseline; billed per GB stored ($0.023/GB-mo), S3 PUT/GET requests, and CloudFront egress.db:dynamodb: $0/mo fixed instance baseline (the VPC Gateway Endpoint is free); billed per read/write request, table storage ($0.25/GB-mo), and PITR continuous backups ($0.20/GB-mo once data is written).db:redis: ~$9.49/mo fixed baseline ($0.013/hr Valkey 8.0cache.t4g.micro); $0 intra-AZ VPC transfer. Each open PR preview runs its own node while the PR is open.queue:sqs: $0/mo fixed baseline; first 1M requests/mo free, then $0.40 per million requests.ai:bedrock: $0/mo fixed baseline; billed per 1K input/output tokens onInvokeModelcalls.email:ses: $0/mo fixed baseline; $0.10 per 1,000 emails sent.cron: $0/mo fixed baseline (first 14M EventBridge Scheduler invocations/mo free); billed only for Fargate seconds while the cron task runs (per-invocation Lambda billing on--target lambda).
grada add prints the cost impact, refreshes the estimate in your README.md (or DEPLOYMENT.md), and grada apply lists active addons in its pre-flight preview. Reference rates are us-east-2; actual charges vary by region and usage.