Automating File Processing with AWS Lambda, S3, DynamoDB, and SNS: A Serverless Solution
In the modern cloud architecture, serverless solutions allow you to build highly scalable and cost-efficient applications. AWS Lambda is a core component of serverless computing, enabling you to execute code in response to events without the need to manage servers.
In this article, we will explore how to use AWS Lambda in conjunction with Amazon S3, DynamoDB, and Simple Notification Service (SNS) to automatically process files that are uploaded to an S3 bucket. The entire flow will be:
We will use Node.js for the Lambda function and Terraform to provision the infrastructure.
Prerequisites
Step 1: Set up the Infrastructure Using Terraform
Terraform will allow us to easily provision and manage AWS resources.
provider "aws" {
region = "us-east-1"
}
resource "aws_s3_bucket" "file_upload_bucket" {
bucket = "my-file-upload-bucket"
}
resource "aws_dynamodb_table" "file_details" {
name = "file-details-table"
hash_key = "file_id"
read_capacity = 5
write_capacity = 5
attribute {
name = "file_id"
type = "S"
}
attribute {
name = "upload_time"
type = "S"
}
attribute {
name = "status"
type = "S"
}
provisioned_throughput {
read_capacity_units = 5
write_capacity_units = 5
}
}
resource "aws_sns_topic" "file_processed_topic" {
name = "file-processed-topic"
}
resource "aws_lambda_function" "process_file_lambda" {
function_name = "process-file-lambda"
runtime = "nodejs14.x"
handler = "index.handler"
role = aws_iam_role.lambda_exec_role.arn
s3_bucket = aws_s3_bucket.lambda_code_bucket.bucket
s3_key = "lambda_code.zip"
environment {
variables = {
DYNAMODB_TABLE = aws_dynamodb_table.file_details.name
SNS_TOPIC_ARN = aws_sns_topic.file_processed_topic.arn
}
}
}
resource "aws_lambda_permission" "allow_s3_trigger" {
statement_id = "AllowS3Trigger"
action = "lambda:InvokeFunction"
principal = "s3.amazonaws.com"
function_name = aws_lambda_function.process_file_lambda.function_name
source_arn = aws_s3_bucket.file_upload_bucket.arn
}
resource "aws_s3_bucket_object" "lambda_code" {
bucket = aws_s3_bucket.lambda_code_bucket.bucket
key = "lambda_code.zip"
source = "path_to_your_lambda_code/lambda_code.zip"
}
resource "aws_s3_bucket" "lambda_code_bucket" {
bucket = "my-lambda-code-bucket"
}
resource "aws_s3_bucket_notification" "s3_to_lambda" {
bucket = aws_s3_bucket.file_upload_bucket.bucket
lambda_function {
events = ["s3:ObjectCreated:*"]
filter_prefix = "uploads/"
lambda_function_arn = aws_lambda_function.process_file_lambda.arn
}
}
Recommended by LinkedIn
Step 2: Write the Lambda Function in Node.js
We will create a Lambda function in Node.js that processes files, stores the file details in DynamoDB, sends an SNS notification, and deletes the file from S3.
Lambda Function Code (index.js)
const AWS = require('aws-sdk');
const s3 = new AWS.S3();
const dynamoDB = new AWS.DynamoDB.DocumentClient();
const sns = new AWS.SNS();
// DynamoDB Table and SNS Topic
const TABLE_NAME = process.env.DYNAMODB_TABLE;
const SNS_TOPIC_ARN = process.env.SNS_TOPIC_ARN;
exports.handler = async (event) => {
console.log('Received event:', JSON.stringify(event, null, 2));
const s3Event = event.Records[0].s3;
const bucketName = s3Event.bucket.name;
const fileName = s3Event.object.key;
// Extract file details
const fileId = fileName.split('/')[1]; // Assuming file path is "uploads/{fileId}/{fileName}"
const uploadTime = new Date().toISOString();
try {
// Step 1: Process the file
console.log(`Processing file: ${fileName}`);
// In this example, the file is simply being processed by logging the details.
// You can add more file processing logic here, like parsing the file, etc.
// Step 2: Store the file details in DynamoDB
const dynamoDbParams = {
TableName: TABLE_NAME,
Item: {
file_id: fileId,
file_name: fileName,
upload_time: uploadTime,
status: 'Processed'
}
};
await dynamoDB.put(dynamoDbParams).promise();
// Step 3: Send notification via SNS
const snsMessage = `File ${fileName} has been processed and stored successfully.`;
const snsParams = {
Message: snsMessage,
TopicArn: SNS_TOPIC_ARN
};
await sns.publish(snsParams).promise();
// Step 4: Delete the file from S3
const s3DeleteParams = {
Bucket: bucketName,
Key: fileName
};
await s3.deleteObject(s3DeleteParams).promise();
console.log(`File ${fileName} has been deleted from S3.`);
return {
statusCode: 200,
body: JSON.stringify('File processed successfully!')
};
} catch (error) {
console.error('Error processing file:', error);
return {
statusCode: 500,
body: JSON.stringify('Error processing file')
};
}
};
Step 3: Explanation of the Lambda Code
Step 4: Deploy and Test the Solution
Conclusion
In this article, we demonstrated how to use AWS Lambda in combination with Amazon S3, DynamoDB, and SNS to create a fully serverless solution that automatically processes files uploaded to an S3 bucket. The process includes storing metadata in DynamoDB, sending notifications via SNS, and cleaning up files from S3.
By using AWS Lambda for event-driven computing, this solution scales automatically and efficiently. It also highlights the ease of using Terraform to provision and manage the infrastructure.
This architecture is ideal for various use cases, such as processing images, analyzing documents, or performing data transformations on uploaded files.