v0.1.0 · open source · Apache-2.0

Run AWS Lambda, SQS and DynamoDB locally — without Docker

The dev server AWS Lambda never had.

~/shop — the whole loop, typed livelive
$ pulse init shop --template api-and-worker --lang python
created project shop from template api-and-worker (python) installing python dependencies — done (6.6s)
$ pulse start
⚡ pulse 0.1.0 — shop api http://localhost:3000 routes POST /orders createOrder try curl -X POST localhost:3000/orders -d '{"sku":"A1","qty":2}' ready in 99ms — edits apply live
$ curl -X POST localhost:3000/orders -d '{"sku":"A1","qty":2}'
201 {"id":"e9b4…","status":"pending"} ⚙ sqs order-events → worker · ok 🎉 first background job processed — your async loop works end to end
$ curl localhost:3000/orders/e9b4…
{"id":"e9b4…","status":"processed"} ← the worker got there first
— an API, a queue, a worker, and a database. all local. —
0 msengine readycontainers: 10–30 s
0 mswarm invokeno cold containers
0 MBmemory, app runningDocker stacks: 2 GB+
$0to learn & buildno AWS account needed
measured on every CI run — a slower pulse is a failed build ↗
integrates with what you already useboto3AWS SDK JS v3SAM · CDK · Serverless Framework deploysGitHub ActionsmacOS · Linuxzsh · bash · fish

pulse is a fast local serverless development environment: build and debug AWS Lambda functions with instant hot reload, real SQS queues, local DynamoDB tables, and event replay. It speaks the real AWS protocols, so your production code runs unchanged — no Docker, no AWS account, no mocks in your handlers.

Already using LocalStack, sam local, or a hand-rolled docker-compose? Here's the trade you're making today:

your current loop

  • start Docker, pull GB images
  • wait 10–30 s for containers
  • hand-wire endpoints & env vars
  • restart after every change
  • lose the event that crashed it

the pulse loop

  • pulse start — one binary
  • ready in 99 ms
  • endpoints auto-configured
  • save a file — it's live
  • replay any event, byte for byte

follow one request

One order, end to end — entirely on your laptop

One request's whole lifecycle — every line below is real output.

A request arrives

plain HTTP · port 3000
$ curl -X POST localhost:3000/orders -d '{"sku":"A1","qty":2}'

The gateway shapes it

an API Gateway v2 event — exactly like production
{"routeKey":"POST /orders","body":"{\"sku\":\"A1\",\"qty\":2}", …}

Your Lambda handler runs

real Runtime API · hot-reloaded code
201 {"id":"e9b4…","status":"pending"}

It queues a background job

local SQS · real wire protocol
⚙ sqs order-events → worker · ok

The worker processes it

visibility timeouts · retries · DLQ if it keeps failing
worker | processed  → status: "processed"

Everything was recorded

payload, logs, outcome — byte for byte
  7275f6ee  Aug  5 01:01   http    createOrder · success · 1ms

So you can time travel

the exact payload, against your current code
$ pulse events replay 7275f6ee
✓ createOrder · success · 0ms

Then ship it, unchanged

pulse is dev-time only
$ sam deploy   # the code that ran here is the code that ships

[01] features

A local cloud that keeps up with your typing

Fidelity from the real AWS protocols, speed from native processes — here's what that buys you every day.

The async loop, actually local

Local SQS queues deliver to workers — visibility timeouts, retries, DLQs — narrated live in your console.

POST /orders
worker
visibility timeoutsautomatic retriesgave up? → orders-dlq

Hot reload, measured in CI

Hot reload for AWS Lambda: save a file, the next request runs the new code.

⌘S handler.py saved
pulse hot-reloads the function
next request runs the new code
0 ms warm invoke · ready in 99 ms · a slow pulse is a failed build

Time travel debugging

Every trigger recorded byte-for-byte — replay yesterday's crash against today's fix.

yesterdaysqs event → worker✗ error
pulse events replay 8931cf5b
todaysame event · fixed code✓ success

Runs like AWS — because it speaks AWS

Plain AWS SDK in your handlers, one env var from pulse — nothing to delete before you deploy.

Lambda Runtime APISQS wire protocolDynamoDB expressions
# handler.py — no pulse imports, no endpoint config
import boto3
sqs = boto3.client("sqs")

# local  → AWS_ENDPOINT_URL points at pulse (set for you)
# prod   → same code. no endpoint. talks to AWS.

State that survives restarts

Local DynamoDB items, queues, history — SQLite under the hood. Free, by default.

PutItem.pulse/datarestart ⟳✓ still there

A CLI that teaches

Run any command bare and it asks instead of erroring. Errors ship their fix.

$ pulse invoke
? which function ›
▸ createOrder
  worker

One 20 MB binary

No Docker, no images, no daemons. Runs happily on battery.

pulse, app running50 MB
a container stack2 GB+

[02] how it works

Empty directory to deployed, in five steps

The complete journey — create, run, build, debug, ship. Every frame below is real output, not a mockup. Click a step or let it play.

pulse init
$ pulse init ? project name › shop ? template › api-and-worker ★ — api + queue + worker + table ? language › python created project shop from template api-and-worker (python) installing python dependencies — done (6.6s)

[03] inspect

X-ray vision for your local cloud

Logs are where debugging starts, not where it ends. pulse records everything and gives you four ways to debug your Lambda functions, queues, and tables locally.

pulse logs --request d90e5295
$ pulse logs --request d90e5295 ⚡ request d90e5295 sqs processWebhook · error · 2ms · 00:08 event { "Records": [ { …the exact payload that arrived, pretty-printed… } … 6 more line(s) logs 00:08:15.903 stderr Traceback (most recent call last): … error RuntimeError: webhook 3625d493 failed on purpose (attempt 3) re-run it against your current code: pulse events replay d90e5295

One id, the whole story: the exact payload that arrived, everything the function printed, how it ended — and the command to re-run it.

[04] why pulse

Local serverless development is broken. Here's the fix.

Why pulse exists

Express has nodemon. Next has next dev. Vite is the dev server. Rails has bin/dev.

AWS Lambda never got one.

pulse changes that.

Serverless made deployment easy — and development weirdly hard. The workarounds:

  • Deploy to debug — minutes per iteration, a real AWS bill per log line
  • Mock everything — tests that pass against code that isn't real
  • Emulate in Docker — GB images, slow containers, config drift

Why not Docker?

  • Startup. Containers boot in tens of seconds; pulse is ready in ~99 ms.
  • Memory. Gigabytes idle vs ~50 MB for a whole app.
  • Iteration. Rebuild-and-restart vs save-and-it's-live.
  • Fidelity. pulse speaks the real Lambda Runtime API and SQS/DynamoDB wire protocols — the AWS SDK can't tell the difference.

pulse start — your local cloud coming online

gatewayhttp · localhost:3000
functionsLambda Runtime API · Node + Python
queuesSQS · retries · DLQs
tablesDynamoDB · SQLite-backed
ready in 99 msedits apply live

How it's put together

One native process, one SQLite file — this is pulse start:

your requestcurl :3000
gatewayAPI Gateway events
Lambda fnreal Runtime API
SQS queueretries · DLQ
worker fnbackground job
DynamoDBSQLite on disk

HTTP becomes API Gateway events, handlers run on the real Runtime API, the SDK points at pulse through one env var, queues retry into DLQs, everything persists to disk.

[05] use cases

What people build with pulse

If it's Lambda + HTTP + SQS + DynamoDB, it runs locally — the whole loop, not a fragment of it.

REST APIs on Lambda

Routes hit real Lambda handlers, hot reload on every save.

Webhook receivers

Ack fast, retry async — then replay the exact delivery that failed.

Background jobs & queue workers

The full SQS → worker → DLQ loop, running on your machine.

Event-driven systems

Chain functions through queues; every event keeps its story.

Learning AWS serverless

No account, no bill — four templates from first function to full app.

Prototyping

Build offline on a plane; deploy the same code with SAM or CDK.

built forbackend engineersAWS developersplatform teamsstartupsindie hackersstudents learning AWS

[06] templates

A learning path, not a pile of boilerplate

Each starter adds exactly one concept. All ship in Python and Node, use the plain AWS SDK, and run unchanged in real AWS.

$ pulse init -t hello

One function behind GET /hello — the smallest possible start.

your first function

$ pulse init -t todo-api

Real CRUD on one DynamoDB table: create, list, complete, delete.

+ a real table

$ pulse init -t webhook-relay

Ack-fast webhooks with retries and a dead-letter queue.

+ a queue & DLQ

$ pulse init -t api-and-worker ★

The full loop: API + queue + worker + table, wired and narrated.

everything together

[07] compare

Built for the inner loop

Searching for a LocalStack alternative, or wondering how pulse compares to sam local? Different tools do different jobs — here's the honest version.

cold start to working

pulse99 ms
container stacks10–30 s

memory while developing

pulse~50 MB
Docker stacks2 GB+

bars drawn to linear scale — the sliver is the point

pulsesam localLocalStack
Cold start to working~100 mscontainer per invoke10–30 s container
Code changesave → donemostly re-invokeredeploy / config
Queue → worker → DLQ locally out of the boxnot availablevia deploy cycle
Event replay & request stories built in
Requirementsone 20 MB binaryDockerDocker, GB-scale image
Typical memory while developing~50 MB100s of MB (containers)GBs (Docker image)
Data persists across restarts free, defaultn/apaid tier

Different tools for different jobs. LocalStack emulates ~100 services and tests your infrastructure code; SAM deploys. pulse owns the five hundred iterations before staging — and pairs with either at deploy time, because your code is vanilla SDK throughout.

Honesty by design. pulse does one workflow completely — CRUD APIs with background jobs (HTTP, SQS, DynamoDB, Lambda). Everything outside that subset fails loudly with a message saying exactly what isn't supported. Never silently wrong. S3, SNS, EventBridge, Step Functions: on the roadmap, not pretended.

Works today

  • AWS Lambda functions — Node.js & Python, real Runtime API
  • HTTP APIs — API Gateway v1/v2 events, {param} & {proxy+} routes
  • SQS queues — visibility timeouts, retries, dead-letter queues
  • DynamoDB — CRUD, Query/Scan, condition & update expressions
  • Hot reload for code and pulse.yaml
  • Event replay, request stories, live monitor, tables browser
  • SQLite persistence across restarts

On the roadmap

  • S3 buckets
  • SNS topics
  • EventBridge rules
  • Step Functions

Until then, touching an unsupported service fails loudly with a clear message — pulse never silently fakes a response it can't honor.

the inner loop is yoursInstall pulse Star on GitHub

deep dives: pulse vs LocalStack → · pulse vs sam local →

[08] faq

Questions people actually ask

Can I run AWS Lambda locally with pulse?

Yes. pulse runs your Lambda functions natively on your machine against the real Lambda Runtime API — the same contract AWS uses in production. Node.js and Python are supported, no Docker is required, and the engine is ready in about 100 milliseconds.

Is pulse a LocalStack alternative?

For the inner development loop, yes. LocalStack emulates ~100 AWS services inside Docker and shines at testing infrastructure code. pulse does one workflow completely — Lambda, HTTP, SQS, DynamoDB — natively, in milliseconds, with dev-server ergonomics: hot reload, event replay, a live monitor. Many teams build with pulse and verify infra with LocalStack or a staging account.

Does pulse replace sam local?

They do different jobs. sam local spins up a container per invocation and can't run the queue → worker → dead-letter-queue loop continuously. pulse runs your whole app as a long-lived local cloud. Your deploy pipeline keeps using SAM (or CDK) — pulse never touches it.

Does pulse require Docker?

No. pulse is one ~20 MB binary that runs your functions as native processes. A complete app idles around 50 MB of memory — no images to pull, no containers to boot.

Does pulse work with boto3 and the AWS SDK?

Yes. Handlers use the plain AWS SDK — boto3 in Python, AWS SDK for JavaScript v3 in Node. pulse sets AWS_ENDPOINT_URL for your functions automatically, so the same code talks to pulse locally and to real AWS in production.

Which languages does pulse support?

Node.js and Python today. Every template ships in both, and handlers are plain SDK code with no pulse imports to remove later.

Does pulse work offline?

Yes. Functions, queues, tables, and event history all live on your machine in SQLite. Build on a plane — no AWS account needed.

Can I debug SQS queues locally?

Yes. pulse runs local SQS queues with visibility timeouts, automatic retries, and dead-letter queues. Peek at waiting messages without consuming them, watch deliveries live, and replay the exact event that failed.

Does my data survive restarts?

Yes. DynamoDB items, queued messages, and event history persist in .pulse/data (SQLite). Stop the engine, restart tomorrow — everything is still there, free, by default.

How do I deploy an app built with pulse?

With whatever you already use — SAM, CDK, or the Serverless Framework. pulse is development-time only and your code is vanilla AWS SDK throughout, so there is nothing to strip out before deploying.

[09] early signal

What early users say

Deleted a 400-line docker-compose the same afternoon. The queue → worker → DLQ loop just runs — on battery, on a train.
Backend engineer · fintech startup
pulse tour is the best five minutes of CLI onboarding I've seen. Sent it to the whole team; everyone's local env finally matches.
Platform lead · B2B SaaS
Replaying yesterday's crashing payload against today's fix — byte for byte — changed how I debug Lambdas. I don't guess anymore.
Solo founder · indie AWS shop

get started

Your local cloud, one command away

Every modern framework has a dev server.AWS Lambda finally has one.

macOS · recommended
$brew install --cask geetnsh2k1/pulse/pulse

then run pulse tour — five minutes, hands-on, nothing simulated