Why I Built an AWS Node.js Lambda Framework (And What It Solves)

Over the past 8–10 years, I’ve run into the same set of issues again and again when deploying Node.js applications to AWS Lambda—especially those built with the popular Express.js framework.

While Express is just 219 KB, the dependency bloat is massive—often exceeding 4.3 MB. In the world of serverless, that’s a serious red flag. Every time I had to make things work, it involved wrappers, hacks, or half-hearted workarounds that made deployments messy and cold starts worse.

Serverless and Express Don’t Mix Well

In many teams I’ve worked with, the standard approach was a big, monolithic Express app. And every time developers tried to work in parallel, we hit code conflicts. This often slowed development and created complex merge scenarios.

When considering serverless, we often used the “one Lambda per activity” pattern—cleaner, simpler, more manageable. But without structure or scaffolding, building and scaling APIs this way felt like reinventing the wheel.

A Lean Framework Born From Frustration

During a professional break recently, I decided to do something about it. I built a lightweight, Node.js Lambda framework designed specifically for AWS:

🔗 Try it here – http://bz2.in/njsfra

Base size: ~110 KB
After build optimization: Can be trimmed below 60 KB
Philosophy: Lazy loading and per-endpoint modularity

This framework is not just small—it’s structured. It’s optimized for real-world development where multiple developers work across multiple endpoints with minimal overlap.

Introducing cw.js: Scaffolding From OpenAPI

To speed up development, the framework includes a tool called cw.js—a code writer utility that reads a simplified OpenAPI v1.0 JSON definition (like api.json) and creates:

Routing logic
A clean project structure
Separate JS files for each endpoint

Each function is generated as an empty handler—ready for you to add business logic and database interactions. Think of it as automatic boilerplate—fast, reliable, and consistent.

You can generate the OpenAPI definition using an LLM like ChatGPT or Gemini. For example:

Prompt:
Assume the role of an expert JSON developer.
Create the following API in OpenAPI 1.0 format:
[Insert plain-language API description]

Why This Architecture Works for Teams

No more code conflicts: Each route is its own file
Truly parallel development: Multiple devs can work without stepping on each other
Works on low-resource devices: Even a smartphone with Termux/Tmux can run this (see: tmux video)

The Magic of Lazy Loading

Lazy loading means the code for a specific API route only loads into memory when it’s needed. For AWS Lambda, this leads to:

✅ Reduced cold start time
✅ Lower memory usage
✅ Faster deployments
✅ Smaller, scalable codebase

Instead of loading the entire API, the Lambda runtime only parses the function being called—boosting efficiency.

Bonus: PHP Version Also Available

If PHP is your stack, I’ve built something similar:

PHP Micro Framework: https://github.com/jthoma/phpmf
Stub Generator Tool: https://github.com/jthoma/phpmf-api-stub-generator

The PHP version (cw.php) accepts OpenAPI 3.0 and works on similar principles.

Final Thoughts

I built this framework to solve my own problems—but I’m sharing it in case it helps you too. It’s small, fast, modular, and team-friendly—ideal for serverless development on AWS.

If you find it useful, consider sharing it with your network.

👉 Framework GitHub
👉 Watch the dev setup on mobile

Get My IP and patch AWS Security Group

My particular use case was that In my own AWS Account where I do most of the R&D I had one security group which was only for me doing SSH into EC2 instances. Way back in 2020 during pandemic season, had to go freelance for sometime while in notice period with one company and in negotiation with another one. Well this time I was mostly connected from mobile hotspot switching from JIO on Galaxy M14 to Airtel on Galaxy A54 and BSNL on second sim of M14 and this was causing my security group update a real pain.

Basically being lazy and having devops and automation since long back. Started working on an idea an the outcome was an AWS Serverless clone of what is my ip service which is named echo my ip. Check it out on github. The nodejs code and aws sam template to deploy is given over there.

Next using the standard Ubuntu terminal text editor added the following to the .bash_aliases file.

sgupdate()
{
  currentip=$(curl --silent https://{api gateway url}/Prod/ip/)
  /usr/local/bin/aws ec2 describe-security-groups --group-id $AWS_SECURITY_GROUP > /dev/shm/permissions.json
  grep CidrIp /dev/shm/permissions.json | grep -v '/0' | awk -F'"' '{print $4}' | while read cidr;
   do
     /usr/local/bin/aws ec2 revoke-security-group-ingress --group-id $AWS_SECURITY_GROUP --ip-permissions "FromPort=-1,IpProtocol=-1,IpRanges=[{CidrIp=$cidr}]"
   done   
  /usr/local/bin/aws ec2 authorize-security-group-ingress --group-id $AWS_SECURITY_GROUP --protocol "-1" --cidr "$currentip/32"
}

alias aws-permit-me='sgupdate'

I already have a .env file for every project I am handling and a cd command will check for existance of .env and source it in case it exists.

cwd(){
  cd $1
  if [ -f .env ] ; then
    . .env
  fi
}

alias cd='cwd'

The env file is of structure as follows with coresponding values after the ‘=’ ofcourse.

export AWS_DEFAULT_REGION=
export AWS_ACCESS_KEY_ID=
export AWS_SECRET_ACCESS_KEY=
export AWS_SECURITY_GROUP=
export AWS_SSH_ID=
export AWS_ACCOUNT=

It’s a common problem for people working from home with dynamic IPs to manage firewall rules. Automating the process with a serverless function and a shell alias is a great way to simplify things. Sharing on github is to help others and provide back to the community.

This method provides some advantages

  • Automation: Eliminates the tedious manual process of updating security group rules.
  • Serverless: Cost-effective, as you only pay for the compute time used.
  • Shell Alias: Provides a convenient and easy-to-remember way to trigger the update.
  • GitHub Sharing: Makes the solution accessible to others.
  • Secure: Security Group Modification uses aws cli and credentials in terminal environment

Choosing the Right Database for High-Performance Web Applications on AWS

In any web application project, selecting the optimal database is crucial. Each project comes with unique requirements, and the final decision often depends on the data characteristics, the application’s operational demands, and future scaling expectations. For my most recent project, choosing a database meant evaluating a range of engines, each with strengths and trade-offs. Here, I’ll walk through the decision-making process and the architecture chosen to meet the application’s unique needs using AWS services.

Initial Considerations

When evaluating databases, I focused on several key factors:

  • Data Ingestion and Retrieval Patterns: What type of data will be stored, and how will it be accessed or analyzed?
  • Search and Select Complexity: How complex are the queries, and do we require complex joins or aggregations?
  • Data Analysis Needs: Will the data require post-processing or machine learning integration for tasks like sentiment analysis?

The database engines I considered included MariaDB, PostgreSQL, and Amazon DynamoDB. MariaDB and PostgreSQL are widely adopted relational databases known for reliability and extensive features, but DynamoDB is particularly designed to support high-throughput applications on AWS, making it a strong candidate.

The Project’s Data Requirements

This project required the following data structure:

  • Data Structure: Each row was structured as JSON, with a maximum record size of approximately 1,541 bytes.
  • Attributes: Each record included an asset ID (20 chars), user ID (20 chars), a rating (1 digit), and a review of up to 1,500 characters.
  • Scale Expectations: Marketing projections suggested rapid growth, with up to 100,000 assets and 50,000 users within six months, resulting in a peak usage of about 5,000 transactions per second. Mock Benchmarks and Testing

To ensure scalability, I conducted a benchmarking exercise using Docker containers to simulate real-world performance for each database engine:

  • MariaDB and PostgreSQL: Both performed well with moderate loads, but resource consumption spiked sharply under simultaneous requests, capping at around 50 transactions per second before exhausting resources.
  • Amazon DynamoDB: Even on constrained resources, DynamoDB managed up to 24,000 requests per second. This performance, combined with its fully managed, serverless nature and built-in horizontal scaling capability, made DynamoDB the clear choice for this project’s high concurrency and low-latency requirements. Amazon DynamoDB – The Core Database

DynamoDB emerged as the best fit for several reasons:

  • High Availability and Scalability: With DynamoDB, we can automatically scale up or down based on traffic, and AWS manages the underlying infrastructure, ensuring availability across multiple regions.
  • Serverless Architecture Compatibility: Since our application was API-first and serverless, built with AWS Lambda in Node.js and Python, DynamoDB’s seamless integration with AWS services suited this architecture perfectly.
  • Flexible Data Model: DynamoDB’s schema-less, JSON-compatible structure aligned with our data requirements.

Read more about Amazon DynamoDB.

Extending with Sentiment Analysis: The DynamoDB and Elasticsearch Combo

The project’s requirements eventually included sentiment analysis and scoring based on user reviews. Full-text search and analysis aren’t DynamoDB’s strengths, especially considering the potential cost of complex text scanning. So, we created a pipeline to augment DynamoDB with Amazon OpenSearch Service (formerly Elasticsearch Service), which can handle complex text indexing and full-text queries more cost-effectively.

  • DynamoDB Streams: Enabled DynamoDB Streams to capture any changes to the data in real time. Whenever a new review was added, it triggered a Lambda function.
  • Lambda Processing: The Lambda function post-processed the data, calculating preliminary sentiment scores and preparing it for indexing in Amazon OpenSearch Service.
  • OpenSearch Indexing: The review data, now pre-processed, was indexed in OpenSearch for full-text search and analytics. This approach allowed efficient searching without burdening DynamoDB.

Read more about Amazon OpenSearch Service.

Leveraging Amazon S3 and AWS Athena for Historical Analysis

With time, the volume of review data would grow significantly. For long-term storage and further analysis, we used Amazon S3 as a durable and cost-effective storage solution. Periodically, the indexed data in OpenSearch was offloaded to S3 for deeper analysis using Amazon Athena.

  • Amazon S3: Enabled periodic data archiving from OpenSearch, reducing the load and cost on OpenSearch. S3 provided a low-cost, durable storage solution with flexible retrieval options.
  • Amazon Athena: Athena allowed SQL querying on structured data in S3, making it easy to run historical analyses and create reports directly from S3 data.

This setup supported large-scale analytics and reporting, allowing us to analyze review trends and user feedback without overburdening the application database.

Read more about Amazon S3 and Amazon Athena.

Final Architecture and Benefits

The final architecture leveraged AWS’s serverless services to create a cost-effective, high-performance database system for our application. Here’s a breakdown of the components and their roles:

  • DynamoDB: Primary database for high-throughput, low-latency data storage.
  • DynamoDB Streams & Lambda: Enabled real-time data processing and integration with OpenSearch.
  • Amazon OpenSearch Service: Provided efficient full-text search and sentiment analysis.
  • Amazon S3 & Athena: Archived data and performed large-scale, cost-effective analytics.

This combination of DynamoDB, OpenSearch, and S3, with Athena for analytics, proved to be an efficient architecture that met all project requirements. The AWS ecosystem’s flexibility allowed us to integrate services tailored to each specific need, maintaining cost-effectiveness and scalability.

  • #DynamoDB #OpenSearch #AmazonS3 #AWSAthena #AWSLambda #Serverless #DatabaseSelection #CloudArchitecture #DataPipeline

This architecture and service setup provides a powerful example of how AWS’s managed services can be leveraged to achieve cost-effective performance and functionality.

Export Cloudwatch Logs to AWS S3 – Deploy using SAM

With due reference to the blog which helped me in the right direction, the Tensult blogs article Exporting of AWS CloudWatch logs to S3 using Automation, though at some points I have deviated from the original author’s suggestion.

Some points are blindly my preference and some other due to the suggested best practices. I do agree that starters, would be better off with setting IAM policies with ‘*’ in the resource field. But when you move things into production it is recommended to use least required permissions. Also, some critical policies were missing from the assume role policy. Another unnecessary activity was the checking of the existence of s3 bucket and attempt to create if not exists, at each repeated execution. Again for this purpose the lambda role needed create bucket permission. All these were over my head, and the outcome is this article.

Well if you need CloudWatch logs to be exported to S3 for whatever reason, this could save your time a lot, though this needs to be run in every different region where you need to deploy the stack. Please excuse me as the whole article expects to have aws-cli and sam-cli pre-installed.

Continue reading “Export Cloudwatch Logs to AWS S3 – Deploy using SAM”