Build an AI Document Summarizer on AWS
Build a serverless pipeline that auto-summarizes documents using OpenAI and AWS Lambda.
Introduction
30 Second Summary
Every day, professionals drown in documents they don't have time to read. What if uploading a file was all it took to get a concise summary back automatically?
In this project, you will build an event-driven AI pipeline on AWS that summarizes text documents the moment they are uploaded to cloud storage. The pipeline uses Amazon S3, AWS Lambda, and the OpenAI API to create a fully automated workflow that requires zero human intervention.
What You'll Build
An intelligent document processing pipeline that automatically reads uploaded text files, sends them to an AI model for summarization, and saves the generated summaries back to cloud storage.
By the end of this project, you'll have:
- A Lambda Layer and IAM role that give your serverless function secure access to the OpenAI Python library.
- An S3 bucket with event notifications that automatically triggers your Lambda function when documents are uploaded.
- A working Python Lambda function that reads uploaded documents, sends them to OpenAI for AI-powered summarization, and saves the results back to S3.
- Secret Mission: Add email notifications using SNS so you get alerted whenever a new summary is generated.
Are there any prerequisites?
You need an AWS account and an OpenAI API key before starting. You also need Python installed on your local machine for packaging a Lambda Layer in Step 1.
Package the OpenAI Library as a Lambda Layer
Your Lambda function needs the OpenAI Python library to communicate with the AI model. However, AWS Lambda's runtime environment only includes the Python standard library and boto3.
A Lambda Layer is a ZIP archive that provides additional libraries to your function at runtime. In this step, you will package the OpenAI library into a Layer that your function can import.
In this step, get ready to:
- Install the OpenAI Python library with Linux-compatible wheels.
- Compress the library into a ZIP file formatted for Lambda.
- Upload the ZIP to AWS as a Lambda Layer.
Install the OpenAI library with Linux-compatible wheels
Lambda runs on Amazon Linux. Even if you are developing on Windows or macOS, you need Linux-compatible package binaries for your Layer to work.
- Press Cmd+Space (macOS) or the Windows key (Windows) to open your search bar.
- Type Terminal (macOS) or PowerShell (Windows) and press Enter to open it.
- Move to your Desktop by running this command:
cd ~/Desktop
- Create your project folder and move into it by running these commands:
mkdir ai-summarizer-layer
cd ai-summarizer-layer
- Confirm the folder was created by running:
ls
You should see the ai-summarizer-layer folder listed in your Desktop directory.
- Install the OpenAI library into a python subdirectory by running this command:
pip install openai --platform manylinux2014_x86_64 --only-binary=:all: --target python
What does this command do?
- --platform manylinux2014_x86_64 forces pip to download Linux-compatible binaries, even if you are on macOS or Windows.
- --only-binary=:all: ensures pip only downloads pre-built wheel files instead of compiling from source.
- --target python installs everything into a folder called python in your current directory. This matches the folder structure Lambda expects.
- Verify the library was installed by running:
ls python
You should see folders like openai, pydantic, and httpx listed in the output.
Seeing an error during install?
- If you see pip: command not found, try using pip3 instead of pip. Some systems install Python 3 under the pip3 command.
- If pip downloads files but the python folder is empty, make sure you included all three flags exactly as shown.
- Help me debug my pip install error.
Compress the library into a ZIP file
Lambda Layers require your packages to be inside a top-level python/ directory within a ZIP archive. Your folder already has this structure.
- Create the ZIP file by running this command:
macOS
zip -r openai-layer.zip python/
Windows
Compress-Archive -Path .\python -DestinationPath .\openai-layer.zip
- Confirm the ZIP file was created by running:
ls
You should see openai-layer.zip alongside the python folder in the output.
Don't see the ZIP file?
- Make sure you are running the command from inside the ai-summarizer-layer folder, not from the Desktop.
- On Windows, make sure you are using PowerShell, not Command Prompt. The Compress-Archive command is a PowerShell cmdlet.
- Help me fix my ZIP file creation.
Upload the Layer to AWS Lambda
Now that you have the ZIP file, you will upload it to AWS as a Lambda Layer. This makes the OpenAI library available to any Lambda function that uses this Layer.
- Open your browser and sign in to the AWS Management Console.
- In the search bar at the top, type Lambda and select Lambda from the results.
- In the left sidebar, click Layers.
- Click Create layer.
- In the Name field, enter openai-layer.
- Select Upload a .zip file and click Upload.
- Navigate to your ai-summarizer-layer folder on your Desktop and select openai-layer.zip.
- Under Compatible runtimes, select python3.13.
- Under Compatible architectures, select x86_64.
- Click Create.
You should see a success banner confirming your Layer was created. The page displays Version 1 of your openai-layer.
Why a Lambda Layer instead of bundling the library?
Bundling libraries directly into your function's deployment package works, but it makes your function larger and harder to update. A Layer lets you manage the dependency separately.
You can reuse the same Layer across multiple functions. If OpenAI releases an update, you upload a new Layer version without touching your function code.
Upload failing or Layer creation erroring?
- If the upload fails, check that your ZIP file is under 50 MB. The OpenAI library with its dependencies should be well under this limit.
- If you see a compatibility error later when testing, confirm you selected python3.13 and x86_64 during creation. These must match your Lambda function settings.
- Help me fix my Lambda Layer upload.
Your Layer is ready. Next up, you will create the S3 bucket that stores your input documents and AI-generated summaries.
Create the S3 Bucket and Folder Structure
Your Lambda Layer is ready to go. Now you need a place for documents to land so that your pipeline knows when new work arrives.
In this step, you will create an S3 bucket that acts as the entry point and exit point for your pipeline. Input documents go into one folder, and AI-generated summaries come out in another.
In this step, get ready to:
- Create an S3 bucket with a globally unique name.
- Set up two folders inside the bucket to separate inputs from outputs.
Create your S3 bucket
Every file in your pipeline needs a home. S3 buckets are globally unique storage containers, meaning no two AWS accounts in the world can share the same bucket name.
- In the AWS Console, click the search bar at the top and type S3.
- Select S3 from the results to open the S3 dashboard.
- Click Create bucket.
- In the Bucket name field, enter ai-summarizer- followed by your initials and a few random numbers. For example: ai-summarizer-jd-8472.
- Leave all other settings as their defaults.
- Scroll to the bottom and click Create bucket.
Why the unique bucket name?
S3 bucket names must be globally unique across all AWS accounts. Adding your initials and random numbers ensures you do not collide with anyone else's bucket name.
You should see a green success banner at the top of the page confirming your bucket was created.
Seeing a 'Bucket name already exists' error?
Someone else in the world already has that exact name. Try adding more random numbers or changing your initials combination.
Help me fix my S3 bucket name error.
Create the uploads and summaries folders
Your pipeline uses prefix-based separation to keep input documents apart from output summaries. This is critical for preventing infinite loops when you add the S3 event trigger later.
- Click on your newly created bucket name to open it.
- Click Create folder.
- Enter uploads as the folder name.
- Click Create folder to confirm.
- Back in the bucket's root view, click Create folder again.
- Enter summaries as the folder name.
- Click Create folder to confirm.
Why two separate folders?
The uploads/ folder is where you will drop input documents. The summaries/ folder is where your Lambda function writes the AI-generated results.
Later, you will configure the S3 event trigger to only fire on the uploads/ prefix. Because the output goes to summaries/, the function never re-triggers itself in an infinite loop.
You should now see both uploads/ and summaries/ listed inside your bucket.
Don't see both folders?
Make sure you navigated back to the bucket's root level before creating the second folder. If you accidentally created summaries/ inside uploads/, delete it and try again from the bucket root.
Help me fix my S3 folder structure.
Your storage is ready. Next up, you will create an IAM role that gives your Lambda function permission to read from and write to these specific folders.
Create the IAM Role for Lambda
Your S3 bucket is set up with uploads/ and summaries/ folders ready to go. Now your Lambda function needs permission to actually read from and write to those folders.
AWS uses IAM roles to control what each service can do. Without an IAM role, your Lambda function would be completely locked out of S3. In this step, you will create a role that gives Lambda only the specific permissions it needs.
In this step, get ready to:
- Create an IAM role with Lambda as the trusted service.
- Attach managed and custom policies for least-privilege S3 access.
Create the IAM role with Lambda as the trusted entity
An IAM role defines which AWS service is allowed to assume it and what actions that service can perform. You will create a role that only Lambda can use.
- In the AWS Console, type IAM in the top search bar and select IAM from the results.
- In the left sidebar, click Roles.
- Click Create role.
- Under Trusted entity type, select AWS service.
- Under Use case, select Lambda.
- Click Next.
What is a trusted entity?
The trusted entity tells AWS which service is allowed to "assume" this role. By selecting Lambda, you are saying only Lambda functions can use these permissions.
No other AWS service or user can assume this role, which keeps your permissions tightly scoped.
Attach permissions policies to the role
Your Lambda function needs two types of permissions: the ability to write logs (so you can debug issues) and the ability to read and write specific S3 objects.
- On the Add permissions page, search for AWSLambdaBasicExecutionRole in the search box.
- Check the box next to AWSLambdaBasicExecutionRole.
- Click Next.
- In the Role name field, enter ai-summarizer-lambda-role.
- Click Create role.
What is AWSLambdaBasicExecutionRole?
This is an AWS managed policy that gives Lambda permission to write logs to CloudWatch. Without it, you would not be able to see any print statements or error messages from your function.
Now you need to add a custom inline policy that grants your Lambda function access to read from uploads/ and write to summaries/ in your S3 bucket.
- In the IAM Roles list, click on ai-summarizer-lambda-role to open it.
- Select the Permissions tab.
- Click the Add permissions dropdown, then select Create inline policy.
- Click the JSON tab in the policy editor.
- Delete any existing content and paste in the following policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::[[BUCKET_NAME="ai-summarizer-your-initials-random-numbers"]]/uploads/*"
},
{
"Effect": "Allow",
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::[[BUCKET_NAME="ai-summarizer-your-initials-random-numbers"]]/summaries/*"
}
]
}
What does this policy do?
This policy follows the principle of least privilege. It only grants the exact permissions your function needs and nothing more.
- s3:GetObject on uploads/* lets Lambda read documents that get uploaded.
- s3:PutObject on summaries/* lets Lambda write the AI-generated summaries back to S3.
Your function cannot delete objects, list the bucket, or access any other folder. If it were compromised, the damage would be minimal.
- Make sure you replace the bucket name in both Resource lines with your actual bucket name (the one you created in the previous step).
- Click Next.
- Enter a name for the policy, such as s3-summarizer-access.
- Click Create policy.
You should now see both AWSLambdaBasicExecutionRole and your inline policy listed under the Permissions policies section of your role.
Don't see your inline policy?
Make sure you clicked into the role first before adding the inline policy. If you are still on the Roles list page, click ai-summarizer-lambda-role to open the role details.
Check that your JSON is valid. A missing comma or bracket will prevent the policy from saving. Look for a red error banner at the top of the policy editor.
help me fix my IAM inline policy
Your IAM role is locked and loaded with exactly the permissions your Lambda function needs. Next up, you will create the Lambda function itself and wire everything together.
Create the Lambda Function
You have all the supporting infrastructure in place: a Lambda Layer with the OpenAI library, an S3 bucket with organized prefixes, and an IAM role with tight permissions.
Now it's time to create the Lambda function itself. This is the compute engine that will run your summarization code whenever a document arrives. In this step, you'll create the function, configure it for AI workloads, and attach the Layer you built earlier.
In this step, get ready to:
- Create a Lambda function with the correct runtime, architecture, and IAM role.
- Configure the function timeout and set up your OpenAI API key as an environment variable.
- Attach the OpenAI Lambda Layer to your function.
Create the Lambda function with your IAM role
AWS Lambda lets you run code without provisioning servers. You define a function, and AWS handles everything else: scaling, patching, and resource management.
- In the AWS Console, type Lambda in the top search bar and select Lambda from the results.
- Click Create function.
- Select Author from scratch.
- Enter ai-document-summarizer in the Function name field.
- Under Runtime, select Python 3.13.
- Under Architecture, select x86_64.
- Expand the Change default execution role section.
- Select Use an existing role.
- In the Existing role dropdown, select ai-summarizer-lambda-role.
- Click Create function.
You should see a success banner at the top of the page confirming your function was created.
Why x86_64 and not arm64?
Your Lambda Layer was packaged with Linux x86_64 wheels. The function's architecture must match the Layer's architecture, otherwise the compiled libraries inside the Layer won't load.
Don't see your role in the dropdown?
Make sure the role you created in the previous step has Lambda selected as the trusted entity (use case). If you selected a different service, the role won't appear here.
Also confirm you're in the same AWS region where you created the role.
Why can't I find my IAM role when creating a Lambda function?
Configure timeout and environment variables
Lambda functions have a default timeout of 3 seconds. That's fine for quick operations, but AI API calls typically take 2-10 seconds to respond. You need to increase the timeout so your function doesn't get cut off mid-request.
- On your function's page, click the Configuration tab.
- In the left sidebar, click General configuration.
- Click Edit.
- Change the Timeout value to 0 min 30 sec.
- Click Save.
Now you'll store your OpenAI API key as an environment variable. This lets your function access the key at runtime without hardcoding it in your source code.
- In the left sidebar under Configuration, click Environment variables.
- Click Edit.
- Click Add environment variable.
- In the Key field, enter OPENAI_API_KEY.
- In the Value field, paste your OpenAI API key (it starts with sk-).
- Click Save.
You should see your environment variable listed with the key OPENAI_API_KEY and a masked value.
What are environment variables?
Environment variables are key-value pairs that your function can read at runtime using code like os.environ["OPENAI_API_KEY"]. They keep sensitive values out of your source code.
For production systems, AWS Secrets Manager is a more secure option. For this learning project, environment variables work well and keep things simple.
Not sure where to find your OpenAI API key?
Go to platform.openai.com, sign in, and navigate to API keys in the left sidebar. If you don't have one yet, click Create new secret key to generate one. Copy it immediately because you won't be able to see it again.
How do I get an OpenAI API key for my Lambda function?
Attach the OpenAI Lambda Layer
Your function needs access to the OpenAI Python library, which lives in the Layer you created in Step 1. Attaching the Layer makes all the packages inside it available to your function's code at runtime.
- Scroll down to the bottom of your function's page to find the Layers section.
- Click Add a layer.
- Select Custom layers.
- In the Custom layers dropdown, select openai-layer.
- Select the latest version (it should be 1 if this is your first time creating it).
- Click Add.
You should see openai-layer listed under the Layers section with a version number next to it.
Don't see your layer in the dropdown?
The layer must have a compatible runtime that matches your function. Your function uses python3.13, so the layer must also list python3.13 as a compatible runtime. If you missed this when creating the layer, go back to Lambda > Layers and create a new version with the correct runtime selected.
Why isn't my Lambda Layer showing up when I try to add it to my function?
Your Lambda function is fully configured and ready to receive code. Next up, you'll write the Python function that reads documents from S3, sends them to OpenAI, and saves the summaries back.
Write the Lambda Function Code
Your Lambda function has the runtime, permissions, and libraries it needs. Now it needs the actual logic that ties everything together.
In this step, you will write the Python code that orchestrates the full summarization workflow. The function reads a document from S3, sends it to OpenAI's Chat Completions API, and saves the AI-generated summary back to your bucket.
In this step, get ready to:
- Write the Lambda function code that reads documents, calls OpenAI, and saves summaries.
- Deploy and test the function with a sample document.
Add the imports and client initialization
The function needs two clients: one for S3 (to read and write files) and one for OpenAI (to generate summaries). You will initialize both outside the handler so they are reused across invocations.
- In the AWS Console, navigate to your ai-document-summarizer Lambda function.
- Click the Code tab.
- Select all the default code in lambda_function.py and delete it.
- Paste the following imports and client initialization at the top of the file:
import json
import os
import urllib.parse
import boto3
from openai import OpenAI
# Initialize clients outside the handler for reuse across invocations
s3_client = boto3.client("s3")
openai_client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])
What does this code do?
- json, os, urllib.parse, and boto3 are standard libraries for working with JSON, environment variables, URL-encoded strings, and AWS services.
- from openai import OpenAI imports the OpenAI client from the Lambda Layer you uploaded earlier.
- openai_client = OpenAI(api_key=os.environ["OPENAI_API_KEY"]) creates the OpenAI client using the environment variable you configured in the previous step.
You will not see a change yet. The next chunk adds the handler function that uses these clients.
Add the Lambda handler function
The handler is the function that AWS Lambda calls when an S3 event arrives. It reads the uploaded document, sends it to OpenAI, and writes the summary back to your bucket.
- Below the client initialization code you just pasted, add the handler function:
def lambda_handler(event, context):
# Get bucket and key from the S3 event
record = event["Records"][0]
bucket = record["s3"]["bucket"]["name"]
key = urllib.parse.unquote_plus(record["s3"]["object"]["key"])
print(f"Processing file: {key} from bucket: {bucket}")
# Read the uploaded file from S3
response = s3_client.get_object(Bucket=bucket, Key=key)
document_text = response["Body"].read().decode("utf-8")
print(f"Document length: {len(document_text)} characters")
# Send the document to OpenAI for summarization
completion = openai_client.chat.completions.create(
model="gpt-4.1-nano",
messages=[
{
"role": "developer",
"content": "You are a document summarizer. Provide a clear, concise summary of the following document. Include the key points and main takeaways.",
},
{
"role": "user",
"content": document_text,
},
],
)
summary = completion.choices[0].message.content
print(f"Summary generated: {len(summary)} characters")
# Write the summary to the summaries/ prefix
original_filename = key.split("/")[-1]
summary_key = f"summaries/summary-{original_filename}"
s3_client.put_object(
Bucket=bucket,
Key=summary_key,
Body=summary.encode("utf-8"),
ContentType="text/plain",
)
print(f"Summary saved to: {summary_key}")
return {
"statusCode": 200,
"body": json.dumps(
{
"message": "Document summarized successfully",
"input_file": key,
"summary_file": summary_key,
}
),
}
What does this function do?
The handler function performs four steps in sequence:
- Extracts the bucket name and file key from the S3 event notification. The urllib.parse.unquote_plus call decodes URL-encoded characters in the filename (like spaces).
- Reads the uploaded file from S3 using get_object and decodes the bytes into a text string.
- Sends the document text to OpenAI's gpt-4.1-nano model with a developer prompt instructing it to summarize. This model costs $0.10 per million input tokens, so each test costs a fraction of a cent.
- Writes the summary to the summaries/ prefix with the filename summary-<original_filename> so you can trace each summary back to its source.
You will not see a result yet. You will deploy and test the function in the next substep.
Seeing red underlines in the editor?
The Lambda code editor may show warnings for the openai import because the editor does not know about your Lambda Layer. This is normal and the code will work when deployed.
Make sure there is no leftover default code above your imports. The file should start with import json on line 1.
help me fix a red underline error in my Lambda code editor
✔️ Awesome, I've got everything!
Great. Double check that your file starts with the imports and ends with the return statement, then move on to deploy and test.
ⓧ I'd like to double check the full code
Here is the complete lambda_function.py file. Make sure your code matches exactly:
import json
import os
import urllib.parse
import boto3
from openai import OpenAI
s3_client = boto3.client("s3")
openai_client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])
def lambda_handler(event, context):
# Get bucket and key from the S3 event
record = event["Records"][0]
bucket = record["s3"]["bucket"]["name"]
key = urllib.parse.unquote_plus(record["s3"]["object"]["key"])
print(f"Processing file: {key} from bucket: {bucket}")
# Read the uploaded file from S3
response = s3_client.get_object(Bucket=bucket, Key=key)
document_text = response["Body"].read().decode("utf-8")
print(f"Document length: {len(document_text)} characters")
# Send the document to OpenAI for summarization
completion = openai_client.chat.completions.create(
model="gpt-4.1-nano",
messages=[
{
"role": "developer",
"content": "You are a document summarizer. Provide a clear, concise summary of the following document. Include the key points and main takeaways.",
},
{
"role": "user",
"content": document_text,
},
],
)
summary = completion.choices[0].message.content
print(f"Summary generated: {len(summary)} characters")
# Write the summary to the summaries/ prefix
original_filename = key.split("/")[-1]
summary_key = f"summaries/summary-{original_filename}"
s3_client.put_object(
Bucket=bucket,
Key=summary_key,
Body=summary.encode("utf-8"),
ContentType="text/plain",
)
print(f"Summary saved to: {summary_key}")
return {
"statusCode": 200,
"body": json.dumps(
{
"message": "Document summarized successfully",
"input_file": key,
"summary_file": summary_key,
}
),
}
Deploy and test the function
Writing code in the Lambda editor does not make it live. You need to deploy it first, then verify it works with a test event that simulates an S3 upload.
- Click the Deploy button above the code editor.
- You should see a green banner that says "Successfully updated the function ai-document-summarizer."
Next, you need a sample document in your S3 bucket for the test to work against.
- On your computer, create a text file called test.txt with a few sentences of content. For example:
Artificial intelligence is transforming how businesses operate. Machine learning models can now process natural language, recognize images, and make predictions with remarkable accuracy. Companies are adopting AI to automate repetitive tasks, improve customer service, and gain insights from large datasets. However, implementing AI successfully requires careful planning, quality data, and ongoing monitoring to ensure models perform as expected.
- In a new browser tab, navigate to your S3 bucket in the AWS Console.
- Open the uploads/ folder.
- Click Upload, then Add files, and select your test.txt file.
- Click Upload to confirm.
Now you will create a test event that simulates S3 sending a notification to your Lambda function.
- Go back to your Lambda function tab.
- Click the Test tab (next to the Code tab).
- Select Create new event.
- Enter testS3Upload as the event name.
- In the Template dropdown, search for and select s3-put.
The template fills in a sample S3 event. You need to update two values so it points to your actual bucket and file.
- In the event JSON, find "name": "example-bucket" and replace example-bucket with your actual bucket name (e.g. ai-summarizer-<your-initials>-<random-numbers>).
- Find "key": "test%2Fkey" and replace the value with uploads/test.txt.
- Click Save.
- Click the Test button to run your function.
What should I see?
After a few seconds, you should see a green "Execution result: succeeded" panel. The response body will contain a JSON object with "message": "Document summarized successfully" along with the input and output file paths.
The function log output will show the file being processed, the document length, and the summary length in characters.
- Navigate to your S3 bucket and open the summaries/ folder.
- You should see a file called summary-test.txt. Click on it and download it to read the AI-generated summary.
Test failed or timed out?
- If you see No module named 'openai': confirm your Lambda Layer is attached. Go to the Code tab and scroll down to the Layers section to verify openai-layer is listed.
- If you see AccessDenied: double check that the bucket name in your test event matches your actual S3 bucket name exactly. Also verify your IAM inline policy uses the correct bucket name.
- If you see Task timed out after 30 seconds: this usually means the OpenAI API key is invalid or the API is unreachable. Verify your OPENAI_API_KEY environment variable under Configuration > Environment variables.
- If you see NoSuchKey: the test.txt file has not been uploaded to the uploads/ folder yet. Upload it before running the test.
help me debug my Lambda function test failure
Your Lambda function is deployed and proven to work. Next, you will connect it to an automatic S3 trigger so documents are summarized the moment they land in your bucket.
Configure the S3 Event Trigger
Your Lambda function works perfectly when triggered manually. The missing piece is automation. Right now, someone would have to log in and click "Test" every time a new document appears.
In this step, you will wire up an S3 event notification so that uploading a .txt file to your uploads/ folder automatically triggers the Lambda function. Zero human intervention required.
In this step, get ready to:
- Add an S3 event trigger to your Lambda function with prefix and suffix filtering.
- Test the full end-to-end pipeline by uploading a document and verifying the summary appears automatically.
Add the S3 event trigger
S3 event notifications let you fire a Lambda function whenever objects are created, deleted, or modified in a bucket. You will filter events to only trigger on .txt files uploaded to the uploads/ prefix.
- In the AWS Console, navigate to Lambda and open your ai-document-summarizer function.
- In the Function overview section at the top, click Add trigger.
- In the Trigger configuration dropdown, select S3.
- In the Bucket field, select your bucket (e.g. ai-summarizer-<your-initials>-<numbers>).
- For Event types, select All object create events.
- In the Prefix field, enter uploads/.
- In the Suffix field, enter .txt.
- Check the I acknowledge that using the same S3 bucket for both input and output is not recommended... checkbox.
- Click Add.
Why is there a recursive invocation warning?
AWS warns you because if a Lambda function writes output to the same bucket that triggers it, you can accidentally create an infinite loop. Each output triggers the function again, which creates another output, and so on.
You are safe here because your trigger only fires on the uploads/ prefix, and your function writes output to the summaries/ prefix. The output never matches the trigger filter, so no loop occurs.
You should see the S3 trigger appear in the Function overview diagram, showing your bucket connected to the Lambda function.
Don't see the trigger in the diagram?
Refresh the Lambda function page. The trigger can take a moment to appear in the overview diagram.
If you get a permissions error, make sure your Lambda function's IAM role has the correct S3 permissions on the bucket you selected.
help me troubleshoot why my S3 trigger failed to add to my Lambda function
Test the full end-to-end pipeline
The trigger is live. Every .txt file that lands in uploads/ will now fire your Lambda function automatically. Time to prove the entire pipeline works without any manual intervention.
- On your local computer, create a new text file with a few paragraphs of content. Name it something different from your earlier test, like article.txt.
- In the AWS Console, navigate to S3 and open your bucket.
- Open the uploads/ folder.
- Click Upload, then Add files.
- Select your article.txt file and click Upload.
- Wait 5-10 seconds for the Lambda function to process the file.
- Navigate to the summaries/ folder in your bucket.
You should see a new file named summary-article.txt. Click on it and download it to read the AI-generated summary of your document.
What is event-driven architecture?
You just experienced it firsthand. Instead of polling or manually checking for new files, the system reacts to events as they happen. The upload event triggers processing automatically.
This pattern scales effortlessly. Whether you upload 1 file or 100 files, each upload independently triggers its own Lambda execution. No scheduling, no cron jobs, no servers sitting idle.
- To verify your function's execution, navigate to CloudWatch in the AWS Console.
- Click Log groups in the left sidebar.
- Find and click the log group named /aws/lambda/ai-document-summarizer.
- Click the most recent log stream to see your function's print statements, including the document length and summary length.
Use CloudWatch to debug
The print() statements in your Lambda code appear here as log entries. If something goes wrong in production, CloudWatch Logs is where you will investigate.
No summary file appearing?
Make sure you uploaded the file directly into the uploads/ folder, not the bucket root. The trigger only fires for objects with the uploads/ prefix.
Confirm your file has a .txt extension. The suffix filter means only .txt files will trigger the function.
Check CloudWatch Logs for error messages. If you see a timeout error, your Lambda function may need more than 30 seconds for longer documents.
help me debug why my S3 event trigger is not invoking my Lambda function
Secret mission
Add SNS Email Notifications
Your pipeline works, but you have to check S3 manually to see if a summary appeared. Real production systems notify stakeholders the moment work is complete. In this secret mission, you will wire up Amazon SNS to send you an email every time a new summary is generated.
Clean Up Your Resources
Clean Up Your Resources
Decide whether to keep your resources running, pause them to come back later, or delete them entirely. This pipeline costs nothing while idle. You only pay when files are uploaded and processed (OpenAI API charges ~$0.01 per document).
Resources you used:
- 1 S3 bucket (free tier: 5GB storage, 20,000 GET, 2,000 PUT requests/month).
- 1 Lambda function (free tier: 1M requests and 400,000 GB-seconds/month).
- 1 Lambda Layer (no ongoing cost).
- 1 IAM role (no cost).
- OpenAI API usage (~$0.01 for testing).
Keep everything running
No action needed. Choose this if you are still actively building or want to keep experimenting with the pipeline.
- Your Lambda function and S3 event trigger have zero idle cost.
- You only incur charges when you upload files (OpenAI API usage).
- S3 storage remains within free tier limits for small test files.
Pause - I'll come back to this later
Lambda and S3 event triggers have no idle cost, so there is nothing to pause. Your resources will sit quietly until you upload another file.
- Optionally, remove the OPENAI_API_KEY environment variable from your Lambda function to prevent accidental API charges if someone uploads a file.
- You can re-add the environment variable later when you return.
Delete - I don't want to use this again
Remove all project resources to fully clean up your AWS account.
- Navigate to S3 in the AWS Console. Select your bucket, click Empty to remove all objects, then click Delete to delete the bucket.
- Navigate to Lambda. Select ai-document-summarizer, click Actions, then Delete.
- Navigate to Lambda > Layers. Select openai-layer and delete all versions.
- Navigate to IAM > Roles. Search for ai-summarizer-lambda-role, select it, and click Delete.
- Delete the local ai-summarizer-layer folder from your computer.
That's a Wrap!
That's a Wrap!
Nice work! You just built an intelligent, fully automated AI pipeline on AWS that summarizes documents the moment they land in your S3 bucket.
Here's what you learned:
- Packaged a third-party Python library as a Lambda Layer and deployed it for serverless use.
- Configured S3 event notifications with prefix filtering to automatically trigger a Lambda function on file upload.
- Wrote a Lambda function that integrates with OpenAI's API to perform AI-powered document summarization with zero manual intervention.
- Added SNS email notifications to create a complete automated alerting system.
Ready to quiz yourself?