DEV Community

RAKSHANEX TECHNOLOGIES
RAKSHANEX TECHNOLOGIES

Posted on

Serverless Without Servers or Pipelines: A Checklist App on Lambda, API Gateway and DynamoDB

I built a serverless checklist app with no servers and no CI/CD pipeline — just Lambda, API Gateway, S3 and DynamoDB, all created from CloudShell with the AWS CLI. This is the story of that build: what it does, how the pieces connect, the one permission bug that hid my data, and what it costs.

What I Built

A small checklist app: create items, list them, and mark them complete. The frontend is a static page on S3, and every action goes through a single HTTP API:

Try it from a terminal:

curl -X POST https://lm1jbisu36.execute-api.us-east-1.amazonaws.com/items -H 'Content-Type: application/json' -d '{"title": "Ship the Weekend Challenge project"}'
curl https://lm1jbisu36.execute-api.us-east-1.amazonaws.com/items
Enter fullscreen mode Exit fullscreen mode

How the pieces connect

  • S3 hosts the static website (HTML, CSS, JavaScript).
  • API Gateway exposes a REST API with routes like POST /items, GET /items, PUT /items/{itemId}/complete and DELETE /items/{itemId}.
  • Lambda (Python 3.12, function serverless-checklist-api) implements all four operations.
  • DynamoDB table serverless-checklist-items in PAY_PER_REQUEST mode stores the data, using an auto-generated item ID as the key.
  • IAM uses a least-privilege role so the function can only read and write that one table.

Everything lives in us-east-1, under AWS account 012517218229. There is no EC2 instance, no container, and no deployment pipeline — the code was deployed straight from CloudShell with AWS CLI commands.

The bug that hid my data

After the first deploy, POST /items returned an ID and a 201 — but GET /items/{itemId} returned "Item not found". The item never reached the database. The cause was the IAM role: the function was deployed with an incorrect role, so it had no DynamoDB permissions and failed silently. The fix was a dedicated least-privilege role with the actions the function needs on that one table. The test runs after the fix all returned HTTP 200.

Why this output matters

This is a build: real infrastructure, real code, real costs. I built it for the AWS Builder Center Weekend Challenge "No Pipeline, No Problem" (Nov 13–16, 2026), where the rule is simple — serverless AWS services only, no servers and no pipelines.

What it costs

Lock-in is close to free. DynamoDB PAY_PER_REQUEST has no base charge for the test volumes I used, Lambda and API Gateway bills for this build were USD 0.00, and the S3 static site costs almost nothing.

What I learned

  • Read error messages literally: a 404 can be a permissions problem, not a missing record.
  • Keep IAM roles per-function, scoped to exactly one table and only the actions the function uses — it converts a silent failure into a clear permission error.
  • Serverless only works if the deploy path is just as simple: build the way you run, with the same CLI commands every time.

What next?

I am adding a short demo video (under 3 minutes) showing the website and the API in action, and more security hardening for the API — throttling, authorizers, and input validation. If you build serverless checklists of your own, what guardrail do you add first?

Top comments (0)