What wisp generates
The exact AWS resources each primitive becomes, so nothing about your deployed stack is a surprise.
wisp produces ordinary AWS infrastructure. There is no wisp control plane, no proxy sitting in front of your traffic, and no resource type you couldn't have written by hand. This page lists exactly what each primitive becomes.
You can always check for yourself:
wisp synthThat writes the real template to .wisp/cloudformation.json without touching your account.
The mapping
| You write | wisp creates |
|---|---|
new Api("main") | An API Gateway HTTP API and a $default stage |
api.get(...) and friends | One Lambda function per route, plus its integration, route, permission, and log group |
new Store("orders", …) | A DynamoDB table, always PAY_PER_REQUEST |
indexes: [...] on a Store | A global secondary index per entry |
new Queue("jobs", …) | An SQS queue, plus a dead-letter queue, plus an event source mapping |
queue.consume(...) | A Lambda function subscribed to that queue |
new Schedule("nightly", …) | An EventBridge Scheduler schedule and a Lambda function |
new Bucket("uploads", …) | An S3 bucket |
bucket.on("created", …) | A Lambda function plus the bucket notification wiring |
new Workflow("checkout", …) | A Step Functions state machine and a Lambda function for its steps |
| any handler | An IAM role scoped to that handler alone |
Every function also gets its own CloudWatch log group with a 14-day retention, so logs don't accumulate cost forever by default.
One function per route
This is the part most worth understanding, because it differs from most frameworks:
API Gateway HTTP API
│
┌──────────────┼──────────────┐
│ │ │
GET /orders POST /orders GET /orders/{id}
│ │ │
▼ ▼ ▼
Lambda #1 Lambda #2 Lambda #3
│ │ │
└──────────────┼──────────────┘
▼
orders (DynamoDB)There is no router. API Gateway invokes the specific function for the matched route directly. That means a slow or failing endpoint can't consume capacity that other endpoints need, and each function's IAM role only covers what that one handler touches.
The trade-off is more functions, which means more cold starts spread across more code paths. Each one is smaller, though, since a route's bundle only contains what that route imports.
Names
Physical names include the app and stage, so stages never collide inside one account:
my-app-dev-orders
my-app-prod-ordersThat's also why --stage matters: two stages are two completely separate sets of resources.
What wisp does not create
- No VPC. Store, Queue, and Bucket are reached over the public AWS APIs with IAM auth, so functions don't need to sit in a VPC. Putting them in one would also add a NAT gateway, which is rejected as always-on.
- No load balancer. API Gateway handles that.
- No servers, containers, or clusters. There's nothing to keep warm.
- Nothing wisp-branded. Delete wisp from your project and the deployed stack keeps running — it's plain CloudFormation.
Escape hatches
When a generated resource needs a property wisp doesn't expose, you don't have to leave the framework — see escape hatches for changing a property, adding a raw resource, or transforming the whole template. The always-on scan still runs afterwards either way.

