Building A Serverless QR Code Generator With AWS
A quick and easy to follow guide with zero experience needed.
Hey, I’m back today, this time with a new challenge for you.
We’re going to be building out a microservice that will act as a QR Code generator.
We’ll do this using serverless services from AWS.
The total cost will be $0 and time to complete this is roughly 5 minutes.
Let’s get started right away!
Architecture Overview
As always, any good solution has to be well thought out before. Let’s take a look at a high-level overview of how we will design this solution:
A client makes a request to an exposed endpoint through a Lambda function URL.
That will trigger a Lambda function which will use a QR code library to generate a QR code.
The Lambda function will store the metadata on DynamoDB
The Lambda function will also upload an image of the QR code to Amazon S3 and store the object URL to DynamoDB as well.
Finally, we’ll return this URL to the client and that will give them their QR code.
Building the solution
Let’s start building the solution within our AWS console. We’ll start with DynamoDB.
Amazon DynamoDB
In the DynamoDB console, create a new table.
Name the table “qrcodes” and use “codeID” for the partition key and “dateCreated” for the sort key.
Create the table.
Amazon S3
Let’s now create a bucket in S3 that will store the images of our QR codes that we will generate.
In the S3 console, create a new bucket.
Name it something unique — I named it “uriel-my-qr-codes” (bucket names must be unique on AWS).
Below, uncheck the Block all public access checkbox (for the purpose of this demo).
Then go ahead and create the bucket.
We now need to enable bucket policies for anyone to read (view and download) QR codes on this bucket.
From your list of buckets, select and open the newly created bucket.
Navigate to the permissions tab.
In Bucket policy, click the edit button to add a policy.
Add the following policy to allow reads to this bucket:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::uriel-my-qr-codes/*"
}
]
}
Notice that on the last line I added my bucket ARN “uriel-my-qr-codes” — you need to change this ARN with your own (shown just above the text editor).
Save changes.
That’s all for S3.
AWS Lambda
In the Lambda console, let’s create a new function.
Use the following configuration:
Choose the “Author from scratch” option
Name the function “generate-qrcode”.
Use the Node JS 20.x runtime.
Add permissions to this Lambda function to read and write to S3 and DynamoDB (quick guide here).
Once you create the function, scroll down to the Code Source section.
Let’s add the following code inside the new VSCode-style editor.
import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3";
import { DynamoDBClient, PutItemCommand } from "@aws-sdk/client-dynamodb";
import QRCode from "qrcode";
// Initialize AWS SDK clients
const s3 = new S3Client({ region: "us-east-1" });
const dynamoDb = new DynamoDBClient({ region: "us-east-1" });
const BUCKET_NAME = "your-bucket-name"; //replace with your bucket name
const TABLE_NAME = "qrcodes";
const randomNum = Math.floor(Math.random() * 100) + 1;
export const handler = async (event) => {
try {
const { text } = event;
// Generate a unique codeID for this QR code
const codeID = `${new Date().toISOString()}-${randomNum}`; //or use a uuid
const dateCreated = new Date().toISOString();
// Generate QR code as a data URL
const qrCodeDataURL = await QRCode.toDataURL(text);
// Decode Base64 image to binary buffer
const base64Data = Buffer.from(
qrCodeDataURL.replace(/^data:image\/\w+;base64,/, ""),
"base64"
);
// Define S3 object parameters
const s3Key = `qrcodes/${codeID}.png`;
const s3Params = {
Bucket: BUCKET_NAME,
Key: s3Key,
Body: base64Data,
ContentEncoding: "base64",
ContentType: "image/png",
};
// Upload QR code image to S3
await s3.send(new PutObjectCommand(s3Params));
// Define the URL for accessing the QR code image
const qrCodeUrl = `https://${BUCKET_NAME}.s3.amazonaws.com/${s3Key}`;
// Prepare metadata for DynamoDB
const dynamoDbParams = {
TableName: TABLE_NAME,
Item: {
codeID: { S: codeID }, // Partition key
dateCreated: { S: dateCreated }, // Sort key
text: { S: text }, // Original text used to generate the QR code
qrCodeUrl: { S: qrCodeUrl } // S3 URL for the QR code image
},
};
await dynamoDb.send(new PutItemCommand(dynamoDbParams));
return {
statusCode: 200,
body: JSON.stringify({ qrCodeUrl, codeID, dateCreated }),
};
} catch (error) {
console.error("Error generating and saving QR code:", error);
return {
statusCode: 500,
body: JSON.stringify({ message: "Error generating QR code" }),
};
}
};
The code above will take in a “text” parameter.
(This text param can be data like a website, some plain text to display, an email address or even a vCard. When users will scan the QR code, they will be displayed this text).
Using the qrcode node js library, we create a qr code from the provided text and convert it to an image format.
We then store the file in S3, and store some metadata and the qrcode image URL (in S3) to our DynamoDB table.
We need to do 2 things before the code can work.
Make sure to use your own S3 bucket name, where you see “your-bucket-name” near the top.
Install the qrcode npm dependency.
To install the qrcode library, open up your IDE on your local device and run the command:
npm install qrcode
That will generate a node_modules folder.
Upload that node-modules folder to the Lambda code editor (sidebar) — you can drag and drop it in (red outline below).
Once the folder is uploaded, you are now ready to test out the qrcode generator.
In the left sidebar, click on the Test button. Create a new test and add the following JSON in the Event JSON.
{
"text": "www.google.com"
}
Click on the Save button and then Invoke to run the test.
It works nicely and after 2 seconds I get a 200 response, with the QR code URL.
If I head over to the URL I can see the QR code and scan it.
As intended scanning the QR code with my phone’s camera opens up the page www.google.com in my browser.
To use this with an application or client, you can create a Lambda function URL to expose an endpoint to invoke the Lambda function and generate a new QR code.
To do this, I suggest you this quick and easy guide.
We are done — we’ve successfully created a QR Code generator microservice.
Conclusion
In this challenge, I guide you through creating a microservice using AWS serverless services to generate QR codes, store them in S3, and log metadata in DynamoDB.
I detail the steps of how to configure and create the Lambda function, DynamoDB, and S3 for this challenge, ensuring the generated QR code is accessible via a unique URL.
👋 My name is Uriel Bitton and I’m committed to helping you master Serverless, Cloud Computing, and AWS.
🚀 If you want to learn how to build serverless, scalable, and resilient applications, you can also follow me on Linkedin for valuable daily posts.
Thanks for reading and see you in the next one!