How to Read DynamoDB Data with AWS Lambda

By ·

I wanted to retrieve data from a DynamoDB table using an AWS Lambda function.

Sounds simple enough, right?

Create a database, write a Lambda function, retrieve some data, and call it a day.

Well, AWS had other plans. 💀

My Lambda function ran successfully but couldn’t actually read anything from DynamoDB. And that little plot twist turned into a surprisingly useful lesson about IAM roles, policies, and why AWS doesn’t let services access everything just because you asked nicely.

In this project, I’ll walk through how I connected AWS Lambda to DynamoDB, troubleshot an AccessDeniedException, and secured the connection using the principle of least privilege.

Lambda DynamoDB Access Flow.png

Tools and Technologies

1. Setting Up My DynamoDB Table

I started by creating a DynamoDB table called BookShelf and adding two book records.

DynamoDB is a fully managed NoSQL database that stores data as items containing attributes. Unlike traditional relational databases, DynamoDB doesn’t require every item to have the same attributes, apart from those used in its primary key.

For my table, I used bookId as the partition key.

Under the hood, DynamoDB uses the partition key’s value to determine which partition stores an item, helping distribute and retrieve data efficiently.

Since bookId is my table’s entire primary key, I can use it to retrieve individual books.

BookShelf table with items

2. Creating My AWS Lambda Function

Next, I created an AWS Lambda function to retrieve data from my table.

AWS Lambda is a serverless compute service that lets you run code without provisioning or managing servers yourself. AWS handles the underlying infrastructure and automatically scales execution based on demand.

For this project, my Lambda function uses the AWS SDK for JavaScript to communicate with DynamoDB.

The function does three things:

  1. Accepts a bookId from a JSON test event.
  2. Uses DynamoDB’s GetItem operation to retrieve the corresponding book.
  3. Returns the book data or an error message if something goes wrong.

Understanding Lambda Execution Roles

Every Lambda function needs an IAM execution role, which determines what AWS resources the function can access.

When I created my function using the Lambda console’s default execution role, it included permissions to write logs to Amazon CloudWatch Logs.

However, it didn’t automatically have permission to access DynamoDB. A small detail that was about to become very important. 👀

Lambda function code

3. Testing My Lambda Function

To test my function, I created a JSON test event containing the bookId I wanted to retrieve.

{
  "bookId": 1
}

I ran the test, and AWS displayed a success message.

Except there was one tiny problem.

My function’s response contained an AccessDeniedException. 💀

The invocation itself had completed, but the database operation had failed.

Because my function caught the error and returned it as a response, Lambda reported a successful invocation even though the book wasn’t retrieved.

The error indicated that my function’s execution role lacked permission to perform the dynamodb:GetItem action.

Essentially, Lambda knew what I wanted it to do. It just wasn’t allowed to do it.

AccessDeniedException in Lambda test results

4. Fixing the IAM Permissions

To resolve the error, I needed to grant my Lambda function permission to retrieve items from DynamoDB.

I explored several AWS-managed policies, including:

There’s an important distinction here: reading DynamoDB Streams is not the same as reading items directly from a DynamoDB table.

Since my function needed to retrieve an item using GetItem, I chose AmazonDynamoDBReadOnlyAccess and attached it to my Lambda execution role.

This provided the missing permission, although it granted more access than my function actually needed.

I’d deal with that next.

Attaching AmazonDynamoDBReadOnlyAccess

Testing Again

With the new policy attached, I reran my original test. And this time, my function successfully retrieved the book data! 🎉

The problem wasn’t my code or the database. It was an IAM permission issue.

Successful Lambda Setup

5. Enhancing Security with Least Privilege

At this point, everything worked. But I wasn’t entirely happy with the permissions I’d granted.

Why give my Lambda function read access to all my DynamoDB tables when it only needs to retrieve a book from one?

This is where the principle of least privilege comes in. Least privilege means granting only the permissions required to perform a specific task.

For my project, the function only needed:

Creating an Inline IAM Policy

I created an inline policy attached to my Lambda execution role.

Using the IAM visual policy editor, I selected DynamoDB as the service, GetItem as the allowed action, and specified the ARN of my BookShelf table.

choosing inline IAM policy

The resulting policy follows this structure:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "dynamodb:GetItem",
      "Resource": "arn:aws:dynamodb:REGION:ACCOUNT_ID:table/BookShelf"
    }
  ]
}

Replace REGION and ACCOUNT_ID with the actual values for your AWS environment.

This policy allows Lambda to retrieve individual items from my BookShelf table without granting it access to other tables.

I then removed the broader AmazonDynamoDBReadOnlyAccess policy while retaining the permissions needed for CloudWatch logging.

Updating IAM policies can accidentally break access to resources, so I ran my original Lambda test again.

And it still worked! ✨

what-can-i-say-mia.gif

6. What I Learned

This project took me approximately two hours to complete.

I went in wanting to understand how Lambda retrieves data from DynamoDB and came out with a much better understanding of IAM permissions.

A few things stood out:

I could also extend this project into a simple serverless web application by introducing Amazon API Gateway. A frontend could send requests through API Gateway to Lambda, which would retrieve the required data from DynamoDB.

But that’s a project for another day.

Final Thoughts

The most rewarding part of this project wasn’t simply retrieving data from DynamoDB. It was understanding why my Lambda function couldn’t retrieve it in the first place.

The biggest challenge was figuring out how IAM roles and policies work together, but troubleshooting that AccessDeniedException helped everything click.

Writing code that works is only half the adventure; the other half is convincing AWS to let it run. 💀

Have a project or engineering opportunity in mind? Get in touch with Sonia.

Sonia Lomo

© 2026 Sonia Lomo

LinkedIn𝕏GitHub