Skip to content

manohar6317/aws-cloud-serverless-visiter-counter

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 

Repository files navigation

Serverless Visitor Counter (AWS)

Project Overview

This project is a serverless backend service designed to track and display real-time visitor analytics. Unlike simple static counters, this application leverages Cloud-Native architecture to handle concurrent traffic and data persistence without managing servers.

The core functionality relies on AWS Lambda for compute and Amazon DynamoDB for atomic data storage, ensuring accuracy and high availability.

Technical Architecture

The system uses a completely serverless event-driven architecture:

graph LR
    Client(Web Client) -- HTTPS/Fetch --> API(Lambda Function URL)
    API -- Trigger --> Lambda(AWS Lambda\nPython Backend)
    Lambda -- Atomic Update --> DB[(Amazon DynamoDB\nNoSQL Database)]
    DB -- Return New Count --> Lambda
    Lambda -- JSON Response --> Client
Loading

Data Flow:

  1. Trigger: A frontend client (static website) sends an asynchronous fetch request to the public API endpoint.
  2. Compute: The request triggers an AWS Lambda function written in Python.
  3. Persistence: The function connects to DynamoDB and performs an atomic increment operation. This ensures that if two users visit at the exact same millisecond, both visits are counted correctly (preventing race conditions).
  4. Response: The updated count is returned to the client as a JSON object.

Tech Stack

Component Technology Role
Compute AWS Lambda Serverless execution of backend logic
Database Amazon DynamoDB NoSQL database for low-latency storage
Language Python 3.12 Logic implementation using boto3 SDK
API Function URL Public HTTPS endpoint for the Lambda function
Security AWS IAM Role-based access control (RBAC)
Client JavaScript (ES6) Frontend integration via Fetch API

Backend Implementation

1. Database Schema (DynamoDB)

  • Table Name: VisitorCount
  • Primary Key: id (String)
  • Item Structure: { "id": "main_page", "views": 42 }

2. Lambda Function (Python)

The core logic resides in lambda_function.py. It uses the boto3 library to interact with DynamoDB.

Key Feature - Atomic Counter: Instead of reading the value, adding 1, and writing it back (which causes race conditions), I utilized DynamoDB's set #v = #v + :incr update expression. This happens entirely on the database side for maximum speed and accuracy.

import json
import boto3
from decimal import Decimal

# Initialize DynamoDB Resource
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('VisitorCount')

# Custom Encoder to handle DynamoDB Decimal format
class DecimalEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, Decimal):
            return int(obj)
        return super(DecimalEncoder, self).default(obj)

def lambda_handler(event, context):
    # Atomic update to prevent race conditions
    response = table.update_item(
        Key={'id': 'main_page'},
        UpdateExpression='SET #v = #v + :incr',
        ExpressionAttributeNames={'#v': 'views'},
        ExpressionAttributeValues={':incr': 1},
        ReturnValues="UPDATED_NEW"
    )
    
    view_count = response['Attributes']['views']
    
    return {
        'statusCode': 200,
        'headers': {
            'Content-Type': 'application/json',
            'Access-Control-Allow-Origin': '*'  # CORS Configuration
        },
        'body': json.dumps({'count': view_count}, cls=DecimalEncoder)
    }

Security & IAM Configuration

Security is handled via AWS IAM (Identity and Access Management) to ensure the Principle of Least Privilege:

  • IAM Execution Role: The Lambda function operates under a custom role (UpdateVisitorCount-role) that has permissions strictly limited to reading and writing to the VisitorCount DynamoDB table. It cannot access S3, EC2, or other unrelated services.
  • CORS Configuration: The Function URL is configured with Cross-Origin Resource Sharing (CORS) to allow requests from the portfolio domain, while blocking unauthorized cross-site scripts.

Challenges Solved

Problem: The CORS Error

  • Issue: When fetching the API from the frontend, the browser blocked the request because the API and the website were on different domains.
  • Solution: I configured the Lambda Function URL to return the header Access-Control-Allow-Origin: * and enabled CORS in the AWS Console settings for GET methods.

Problem: Data Type Serialization

  • Issue: DynamoDB returns numbers as Decimal types, which Python's standard json.dumps cannot serialize.
  • Solution: Implemented a custom DecimalEncoder class to convert Decimal types to standard Python int or float before returning the JSON response.

How to Run Locally

  1. Clone the repository.
  2. Install boto3: pip install boto3
  3. Configure AWS Credentials: aws configure
  4. Run the python script (requires a live DynamoDB table connection).

Releases

No releases published

Packages

 
 
 

Contributors

Languages