Project
Workflow Visualizer
Submit a job below and watch it move through a real AWS Step Functions state machine — Validating, Processing, then Complete — with every status change written straight to DynamoDB by the state machine itself. No Lambda sits in that loop at all.
Demo
Submit a Job
This button sends a real request to API Gateway, which starts a Step Functions execution. The timeline below polls a status endpoint and lights up live as the state machine advances.
Privacy notice: nothing personal is collected — each job is just a random id, a status, and two timestamps.
Your job's live status will appear here once you submit one.
Your job
- Submitted
- Validating
- Processing
- Complete
Recent jobs
No jobs submitted yet this session.| Submitted | Job ID | Status |
|---|
Architecture
How It Works
This is a real AWS project, not a mockup. Here's what actually happens between clicking the button above and the timeline reaching Complete — click any step to jump to it, or let it play through on its own.
-
1
Visitor clicks Submit a job
This static page — including this button — is served from S3, the same way as the rest of the site. Clicking it sends a
POST /jobsrequest with an empty body; nothing personal is sent. -
2
Browser calls API Gateway
API Gateway receives the request and proxies it to a Lambda function — the only Lambda involved in the whole submit-and-run path.
-
3
Lambda creates the job and starts the workflow
Lambda writes a new DynamoDB item with status
SUBMITTED, then calls Step Functions'StartExecutionAPI and immediately returns the new job's id to the browser — it doesn't wait for the workflow to finish. -
4
Step Functions runs the state machine
A Standard state machine advances the job through
VALIDATING, a short wait,PROCESSING, another short wait, thenCOMPLETE— around 13 seconds end to end. -
5
Step Functions writes status directly to DynamoDB
Every one of those three transitions is a native
dynamodb:UpdateItemtask built into the state machine definition — there's no Lambda in this part of the path at all. Meanwhile, the browser polls a separateGET /jobs/{id}endpoint every couple seconds and lights up the timeline above to match whatever DynamoDB currently says.
Use Cases
Where This Pattern Fits
Step Functions shows up anywhere a request kicks off work that takes longer than a single API call should reasonably wait for.
Multi-step processing pipelines
Video transcoding, report generation, image processing — any job that moves through distinct stages benefits from a state machine that tracks exactly where each one is.
Order and fulfillment workflows
An order moving through payment, inventory, and shipping steps is a natural fit — each stage's status is queryable at any point, not hidden inside a single opaque function.
Approval and review chains
Anything with a human-in-the-loop wait — a moderation queue, an approval step — pairs naturally with a state machine's ability to sit idle for a long time at no cost.
Pricing
What This Actually Costs
Pay-per-use the whole way through — an unclicked demo costs nothing. These are estimates based on public AWS list pricing, not a guarantee.
What drives the cost
- Step Functions — Standard workflows are billed per state transition; this workflow uses 3 (Validating, Processing, Complete) per job, after a 4,000/month free tier.
- Lambda — one small function on the create-job path, billed per request and per millisecond.
- DynamoDB — on-demand billing for the job table and its recency index; no idle capacity to pay for.
- API Gateway — billed per request across the create/read/list routes.
Design Decisions
Why I Built It This Way
A few choices here aren't the only way to build this — here's the reasoning behind them.
No Lambda inside the state machine
It would have been simpler in one sense to route every
transition through a single generic "update status" Lambda.
Step Functions' native DynamoDB integration — a task state that
calls dynamodb:UpdateItem directly — skips that
extra hop entirely: no Lambda cold start on the path, no
separate function to deploy and grant permissions to, and the
state machine's own execution role only ever needs exactly one
IAM action against exactly one table.
The trigger Lambda writes SUBMITTED, not VALIDATING
Having the API Lambda create the job with status
VALIDATING directly would let two different
pieces of code each claim to be the source of a status
change. Splitting SUBMITTED (written by the API
Lambda) from VALIDATING (the state machine's
own first transition) means every real status change has
exactly one origin.
Standard workflow, not Express
Express workflows are built for high-volume, sub-5-minute, fire-and-forget executions where you don't need to look back at run history. This project is the opposite of that use case — the whole point is watching one execution's history unfold, and Standard workflows keep that execution history queryable in the console long after it finishes.
A GSI instead of a Scan for "recent jobs"
A Scan can't reliably answer "the N most recent rows" once a
table holds more than a handful of items, since it reads
items in whatever order they sit in on disk. A GSI with a
constant partition key and createdAt as the sort
key turns that into an actual sorted Query.
Polling instead of a WebSocket
This project reaches for a simple tool — the browser polling a REST endpoint every couple seconds is plenty responsive for a 13-second workflow, without the extra infrastructure a persistent connection would need.
Architecture Diagram
Full Architecture Diagram
The complete AWS architecture diagram for this project, built with draw.io. Click it to expand full screen.