Professional Documents
Culture Documents
ith AWS Lambda. Serverless Computing is a great way of… | by Anushka Rustagi | 1mg Technology | Medium
Anushka Rustagi
Oct 5, 2020 · 9 min read
To explain why we used Serverless approach AWS Lambda, for PDF generation, we will
take an example of shipping invoice generation on each order delivery.
CPU Utilization: On each order delivery, user is communicated with shipping invoice
PDF. On an average there is about ~20-30K requests per day on order service for
generating PDFs. Generating each PDF on the backend service is a CPU expensive task,
which leads to high cpu consumption and high latency in requests. Also, there are
service restarts in case of high load due to PDF generation. To decouple the PDF
generation process from backend server we shifted it to AWS Lambda. PDF file will be
stored in AWS S3 Bucket and the file link is then shared with user over email. So
hereby, we distributed the load by shifting the process to AWS Lambda.
After releasing PDF generation service on 28th April, 2020 there is a ~40% reduction
in maximum CPU utilisation metric of the backend server. This is after decoupling PDF
generation logic from the backend and generating PDFs through PDF generation
service on AWS Lambda .
Cost Effective: If we wanted to distribute the load only then this code could be
deployed on EC2 instance instead of AWS Lambda but here’s why we didn’t go for it.
https://medium.com/1mgofficial/pdf-generation-with-aws-lambda-627b8dd07c77 2/12
19/02/2021 PDF Generation With AWS Lambda. Serverless Computing is a great way of… | by Anushka Rustagi | 1mg Technology | Medium
In terms of scalability and cost, lambda provided efficient solution. AWS Lambda is
auto scalable so effort in scaling and managing EC2 instances is saved. Even smallest
EC2 instance t2 nano would be costlier for two reasons; First, we need an ALB
(Application Load Balancer) for load balancing between instances, which will add to
the cost. Second, traffic is not evenly distributed always so we would need more EC2
instances than planned and EC2 will consume some memory being allocated. Lambda
can handle the load balancing internally so no extra cost is added while scaling.
Following shows the AWS Lambda Calculation based on inputs observed in production
metrics and lambda settings.
https://medium.com/1mgofficial/pdf-generation-with-aws-lambda-627b8dd07c77 3/12
19/02/2021 PDF Generation With AWS Lambda. Serverless Computing is a great way of… | by Anushka Rustagi | 1mg Technology | Medium
On getting ~0.6 Million requests per month with each invocation duration as 2.5 sec
and memory allocated as 3008 MB, the final calculated amount is 76.50 USD.
The process of generating PDF follows these steps, take input as HTML template, render
it and create an HTML string which is passed to PDF library and string is converted into
PDF file. Code supports jinja templates for rendering HTML and converting the HTML
string to PDF. In order to make PDF generation service generic, it is templatized so that
different backend services will share template S3 location and dynamic data to Lambda
function through API.
https://medium.com/1mgofficial/pdf-generation-with-aws-lambda-627b8dd07c77 4/12
19/02/2021 PDF Generation With AWS Lambda. Serverless Computing is a great way of… | by Anushka Rustagi | 1mg Technology | Medium
1. We are passing the HTML content as buffer to the library and creating PDF instead
of directly creating PDFs on the disk such as PDFKit which increase high I/O ops
2. We used templates for PDF generation to make process generic. Services will pass
there template S3 location which will be used for generating PDFs. To create PDF
we used Jinja templates which html-pdf library supports.
Library uses PhantomJS module internally which is a headless browser. This executable
must be installed on your system. Follow the steps to install
PhantomJS(https://phantomjs.org/download.html).
Prerequisite:
npm i -g serverless
Layer:
A layer is ZIP archive to configure Lambda function to pull in additional code. You can
move runtime dependencies out of your function code by placing them in a layer.
Lambda runtimes include paths in the /opt directory to ensure that your function code
has access to libraries that are included in layers.
service: executables-layer
provider:
name: aws
stage: ${opt:stage, 'dev'}
region: ${opt:region, 'ap-south-1'}
layers:
pdfGenerator:
path: executables
name: pdfGenerator-${self:provider.stage}
description: Executable binaries required to convert html to pdf
https://medium.com/1mgofficial/pdf-generation-with-aws-lambda-627b8dd07c77 5/12
19/02/2021 PDF Generation With AWS Lambda. Serverless Computing is a great way of… | by Anushka Rustagi | 1mg Technology | Medium
resources:
Outputs:
PDFGeneratorLayerExport:
Value:
Ref: PDFGeneratorLayer
Export:
Name: PDFGeneratorLayerLayer-${self:provider.stage}
Structure your layer so that function code can access libraries without additional
configuration. We have created the layer previously, so all the executables that were
deployed are accessible in function like /opt/phantomjs_linux-x86_64.
Code:
We will be creating a simple function that takes HTML template file and dynamic data
for rendering as input and converts it to the PDF. In this example, we will be using Jinja
template engine. We will be uploading the generated PDF file to S3. We are using the
html-pdf library for converting HTML to PDF. To get more info. about the configuration
of html-pdf visit (https://www.npmjs.com/package/html-pdf)
mkdir pdfGenerator
cd pdfGenerator
touch handler.js
We have imported following libraries for PDF generation function. AWS-SDK library is
for using S3 client.
In the code, you can see that we have set some environment variables before the
function. It is very important to set this environment variables to work properly. You
can find more info. about AWS Environment Variables.
https://medium.com/1mgofficial/pdf-generation-with-aws-lambda-627b8dd07c77 6/12
19/02/2021 PDF Generation With AWS Lambda. Serverless Computing is a great way of… | by Anushka Rustagi | 1mg Technology | Medium
process.env.PATH = `${process.env.PATH}:/opt`
process.env.FONTCONFIG_PATH = '/opt'
process.env.LD_LIBRARY_PATH = '/opt'
It is important that we initialise all the argument’s default values prior to avoid getting
exception within the function.
One of the best practices in lambda functions is to initialise all client objects globally so
that client object creation on each invocation is avoided to reduce average duration of
the invocation.
Here we are formatting input data before its used for PDF generation process.
https://medium.com/1mgofficial/pdf-generation-with-aws-lambda-627b8dd07c77 7/12
19/02/2021 PDF Generation With AWS Lambda. Serverless Computing is a great way of… | by Anushka Rustagi | 1mg Technology | Medium
let template_s3_bucket =
transform_payload.template_s3_bucket_details.BUCKET_NAME
let template_s3_key =
transform_payload.template_s3_bucket_details.OBJECT_KEY
let pdf_bucket =
transform_payload.pdf_s3_bucket_details.BUCKET_NAME;
let pdf_file_info =
transform_payload.pdf_s3_bucket_details.PDF_FILE_INFO;
let pdf_file_path = pdf_file_info.PATH
// template Object
let Data = await s3.getObject({ Bucket: template_s3_bucket,
Key: template_s3_key }).promise();
// PDF generation
let file = await exportHtmlToPdf(content, options);
// PDF upload to s3
let upload_args = PDF_UPLOAD_ARGS;
if (pdf_upload_extra_args &&
Object.keys(pdf_upload_extra_args).length){
upload_args = pdf_upload_extra_args
}
upload_args.Bucket = pdf_bucket
upload_args.Key = pdf_file_path
upload_args.Body = file
let file_upload_data = await
s3.upload(upload_args).promise();
// Response formatting
let message = ''
let url = ''
let status
if (file_upload_data.Location){
status = 200
url = file_upload_data.Location
message = 'PDF generated successfully'
}
else{
status = 400
url = ''
message = 'Error in generating pdf'
}
let response_message = {
'message': message,
'version': version,
'resource_lock_id': resource_lock_id
}
let body = {"message": response_message,
"url": url}
return {
'statusCode': status,
'body': JSON.stringify(body)
}
} catch (error) {
return {
'statusCode': 500,
'body': JSON.stringify(error)
}
}
}
exportHtmlToPDF function:
https://medium.com/1mgofficial/pdf-generation-with-aws-lambda-627b8dd07c77 9/12
19/02/2021 PDF Generation With AWS Lambda. Serverless Computing is a great way of… | by Anushka Rustagi | 1mg Technology | Medium
Our function is now ready. Let us now set up the serverless.yml file for deployment
purpose of the script
touch serverless.yml
service: pdfGenerator
provider:
name: aws
runtime: nodejs12.x
stage: ${opt:stage, 'dev'}
region: ${opt:region, 'ap-south-1'}
environment:
S3_BUCKET: file-upload-bucket
functions:
pdfGenerator:
handler: handler.pdfGenerator
layers:
- ${cf:executables-
layer-${self:provider.stage}.PDFGeneratorLayerExport}
# serverless optimization
package:
individually: true
https://medium.com/1mgofficial/pdf-generation-with-aws-lambda-627b8dd07c77 10/12
19/02/2021 PDF Generation With AWS Lambda. Serverless Computing is a great way of… | by Anushka Rustagi | 1mg Technology | Medium
custom:
webpack:
webpackConfig: ../webpack.config.js
includeModules:
forceExclude:
- aws-sdk
packagePath: ../package.json
plugins:
- serverless-webpack
- serverless-offline
We are now ready for deployment. Deploy the function with the following command:
The function is now ready to use. After deployment, you will get an endpoint like
https://xxxxxxxx.execute-api.ap-south-1.amazonaws.com/dev/api/pdfGenerator. The
region can be different for you. Try to invoke the API with any tool you like.
Production Metrics:
https://medium.com/1mgofficial/pdf-generation-with-aws-lambda-627b8dd07c77 11/12
19/02/2021 PDF Generation With AWS Lambda. Serverless Computing is a great way of… | by Anushka Rustagi | 1mg Technology | Medium
Over the time we have monitored Lambda Production Metrics and refactored the PDF
Generator lambda function to improve the average duration of invocations and high
success rate. To Further improve the efficiency of lambda function we are integrating it
to AWS SQS to support queuing mechanism. Thanks for reading the article and I hope
this has helped you. Stay tuned for further article from 1mg.
https://medium.com/1mgofficial/pdf-generation-with-aws-lambda-627b8dd07c77 12/12