Learning AWS Lambda, API Gateway, and S3 by Building Your Own QR Code Generation API

Learning AWS Lambda, API Gateway, and S3 by Building Your Own QR Code Generation API


7 min read

In this tutorial, we will develop a custom QR code generator API and then integrate it into a basic website.

We'll build the API using Node.js and deploy it on AWS Lambda. The API endpoints will be established through API Gateway, and the generated QR codes will be stored in Amazon S3. The only requirement is having an AWS account. If you're within the free tier, following this tutorial should incur no costs, as we'll stay within the free tier limits. However, it's important to delete all AWS resources once you're done practicing to prevent any unexpected charges.

AWS Lambda is a serverless compute service provided by AWS (Amazon Web Services) that allows developers to run code in response to events without having to manage servers or runtime environments. Lambda Supports lots of Runtime environments like Node.js, Python, Go, Ruby, Java, .NET etc. It supports custom runtime environments also. You only pay for the compute time you consume - there is no charge when your code is not running.

Under Free Tier AWS Gives 1,000,000 free requests per month which is 3.2 million seconds of free compute time per month for 12 months.

Step 1: Creating S3 Bucket

We will be creating an S3 bucket. and making content inside it publically accessible so we can access our generated QR codes.

Login into AWS and search s3 in the search bar then click on the first result as shown in the image.

Click on Create Bucket

Now Enter the Bucket name it must be unique. Keep all options as default. and then click on the "create bucket" button at the bottom.

Now After Your bucket is created click on the "Permissions" tab. Click on the Edit button on "Block public access".

uncheck all options and click on "Save Changes". You will be asked to confirm. type confirm.

Now Move down and click on Edit button in "Bucket policy".

Update Bucket Policy like below. Keep in mind to add Your Bucket ARN. You can take it just from above.

  "Version": "2012-10-17",
  "Statement": [
      "Effect": "Allow",
      "Principal": "*",
      "Action": "s3:GetObject",
      "Resource": "<Your ARN>/*"

Now Click on "Save Changes"
Now Our S3 Bucket is ready. All files put inside this bucket now will be publically accessible.

Step 2: Creating a Lambda Function

Search lambda in the search bar then click on the first result as shown in the image.

Now Click on Create Function

Then Select the First Option "Author from scratch" and then Enter the Function name. Also, Runtime should be selected as Node.js. Keep Everything default. and Just click on the "Create Function" button.

You Will come across a window like below.

You can explore this window to learn more.

Go to link https://github.com/Anujsd/lambda-qr-code
And Clone this Repo in your PC.
Open that in your Favourite IDE I will be using vs code.
Open index.mjs go to line number 9 and update the bucket name with your bucket name we just created.

Now Run the Command "npm install" to install node dependencies

Now We are going to create a ZIP of this whole "lambda-qr-code" folder.
For Windows open it in File Explorer select all, right-click and click on compress to zip.

name zip file "lambda-qr-code".
For the Sake of this tutorial, we will be uploading code using zip.
This ZIP file contains all code and node modules required for the lambda function. As we are using custom packages we need to upload node modules in zip format. otherwise, we could have directly written code on the web interface.

Now to upload this ZIP go to lambda in AWS in the "code" section and click on "upload from".

select option ".zip file" and upload that zip file.

After Uploading the File You will see an interface like below.

The code won't be visible in the web interface because the file is too large; however, it's quite straightforward, and you can view it below.

import AWS from 'aws-sdk';
import QRCode from 'qrcode';

// Configure AWS SDK
AWS.config.update({ region: 'us-east-1' });
const s3 = new AWS.S3();

// Define S3 bucket and key
const bucketName = '<s3 bucket name>';
const key = `qr-codes/${Date.now()}.png`;

export const handler = async (event) => {

  // Process POST request
  try {
    let requestBody;
    if (typeof event.body === 'string') {
      requestBody = JSON.parse(event.body);
    } else {
      requestBody = event.body; // Assuming it's already parsed

    const { url } = requestBody;

    if (!url) {
      return {
        statusCode: 400,
        body: JSON.stringify({ message: 'URL is required', body: requestBody }),

    // Generate QR code
    const qrCodeBuffer = await QRCode.toBuffer(url);

    // Upload QR code to S3
    await s3
        Bucket: bucketName,
        Key: key,
        Body: qrCodeBuffer,
        ContentType: 'image/png',

    // Construct the public URL of the QR code
    const publicUrl = `https://${bucketName}.s3.amazonaws.com/${key}`;

    // Return response with CORS headers
    return {
      statusCode: 200,
      body: JSON.stringify({ qrCodeUrl: publicUrl }),
  } catch (error) {
    console.error('Error generating QR code:', error);
    return {
      statusCode: 500,
      body: JSON.stringify({ message: 'Internal Server Error' }),

Now We will be giving our lambda function permission to add generated QR in s3.

for that go to the "Configuration" Tab then "Permissions" and click on the "Role name" link. It will be opened in a new tab.

Now in a newly opened window. click on "Add permissions" and then "Attach policies".

a new window will be opened. Search "s3" in that and select "AmazonS3FullAccess" policy. and click on the "add permissions" button at the bottom.

Now go to lambda Function.

We will be testing If it's working or not.
Click on the "Test" Section. Select options like below and add below JSON which is our test payload.

  "body": {
    "url": "https://anujdube.com/"

Click on "Save" and then click on the "Test" button.
After Successful execution, you will see the output like below. To see detailed logs you can click on the "logs" link.

Now Our lambda function is ready we are going to add an API gateway to this lambda function.

Step 3: Attaching API gateway to lambda function

Search API Gateway in the search bar then click on the first result as shown in the image.

after opening it. Click on the "build" option in HTTP API.

In "Intergrations" select our lambda function as shown below. and add name to API.

click on next. in routes. add a POST route like below.

Now Click on next. keep everything default. and click on the "Create" button.

You will see your API created like below.

Now open your API. On the left-hand side click on the section after "VPC links".

and in there you can see the invoke URL. this is your API URL.

You can use this URL and do a POST request using POSTMAN. It will be successful.

But if you try to use this URL in any application you might get CORS errors like below.

To resolve these errors click on CORS on the left-hand side. and click on "configure"

Add values as below and click on "Save"

Access-Control-Allow-Origin : *

Access-Control-Allow-Headers : Content-Type, x-requested-with

Access-Control-Allow-Methods : OPTIONS, POST

At the moment, we are permitting access from all origins. However, for enhanced security in a production environment, it's advisable to restrict access to just your domain name.

Click on the "save" button.

Now You will not face any CORS Errors While using your API in any app.

Step 4: Integrating the Created API into a Website

Now we will be trying to use the created API in a simple app.

Click on the below link and clone the repo
it just has 3 files.

open script.js

and on line number 1. update your API endpoint

now if you open index.html

you will see UI like below

enter any link to shorten and you will see a QR code generated for that link
you can test if the QR code is correct or not.

Now You can host this website online if needed.

In this way, We developed our custom QR Code generation API utilizing AWS Lambda. If you encounter any issues or spot any errors in the article, please don't hesitate to contact me.