Skip to main content

Walkthrough: Web Visitor Counter Lambda

· 3 min read
Rendy E. Saputra
Software Engineer

Inspired by Cloud Resume Challenge, I started building a high-performance, strongly typed AWS Lambda function backed by Amazon DynamoDB for atomic web visitor counting, triggered via Amazon API Gateway HTTP API (Payload v2).

Currently I have finished working on the Lambda function, and I am working towards the deployment of the API Gateway HTTP API and DynamoDB table. This post is a walkthrough of the source code, testing, and build process, that I and AI pair-programmed together. The source code is available on GitHub.

What Was Built​

1. Source Architecture​

  • src/types.ts: Strongly typed models for CounterRecord, CounterResponse, ErrorResponse, and AppConfig.
  • src/config.ts: Environment variable loader for TABLE_NAME, ALLOW_ORIGIN, DEFAULT_PAGE_ID, and AWS_REGION.
  • src/utils.ts: CORS headers, API Gateway v2 response builders, and pageId sanitization (validates characters and restricts max length to 128 characters).
  • src/counter.ts: DynamoDB atomic operations using AWS SDK v3 DynamoDBDocumentClient:
    • incrementCounter: Uses atomic update expression:
      SET #count = if_not_exists(#count, :zero) + :inc, #updatedAt = :now
    • getCounter: Reads count without incrementing; returns { count: 0, updatedAt: null } for unvisited pages.
  • src/handler.ts: Main AWS Lambda handler (APIGatewayProxyHandlerV2):
    • Handles OPTIONS CORS preflight requests (HTTP 204).
    • Routes POST to increment counter.
    • Routes GET to read counter.
    • Returns HTTP 405 for unsupported HTTP methods.
    • Returns HTTP 400 for malformed input or invalid pageId.
    • Returns HTTP 500 for missing config or database errors.

2. Testing & Tooling​

  • package.json: Configured with @aws-sdk/client-dynamodb, @aws-sdk/lib-dynamodb, esbuild, jest, ts-jest, and aws-sdk-client-mock.
  • jest.config.js: Unit test configuration with ts-jest and coverage thresholds.
  • tests/counter.test.ts: Unit tests for DynamoDB atomic increments and reads.
  • tests/handler.test.ts: End-to-end event routing, CORS, query/body parsing, and error handling.
  • tests/config.test.ts: Environment variable validation tests.
  • tests/utils.test.ts: Sanitization, validation, and CORS tests.
  • README.md: Documentation including DynamoDB table creation, IAM permissions, API Gateway HTTP API setup, and frontend client snippet.

Validation Results​

1. TypeScript Strict Typecheck​

npm run typecheck

Passed with 0 errors.

2. Jest Test Suite with Coverage​

npm run test:coverage
PASS tests/config.test.ts
PASS tests/utils.test.ts
PASS tests/counter.test.ts
PASS tests/handler.test.ts

------------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
------------|---------|----------|---------|---------|-------------------
All files | 96.8 | 90.69 | 85.71 | 96.8 |
config.ts | 100 | 88.88 | 100 | 100 |
counter.ts | 100 | 80 | 100 | 100 |
handler.ts | 93.1 | 100 | 50 | 93.1 |
utils.ts | 97.29 | 94.11 | 100 | 97.29 |
------------|---------|----------|---------|---------|-------------------

Test Suites: 4 passed, 4 total
Tests: 33 passed, 33 total

3. Build & Package Verification​

npm run package
  • Bundled via esbuild to CommonJS Node.js 20 target.
  • Produced dist/visitor-counter.zip (577 KB), verified dist/index.js exports handler.