You can bypass Lambda entirely and have API Gateway talk directly to DynamoDB, and it’s faster and cheaper for simple CRUD operations.
Let’s see it in action. Imagine you have a DynamoDB table named users with a primary key userId (string). You want to allow clients to GET a user by their userId via an API.
First, set up your DynamoDB table.
{
"TableName": "users",
"AttributeDefinitions": [
{
"AttributeName": "userId",
"AttributeType": "S"
}
],
"KeySchema": [
{
"AttributeName": "userId",
"KeyType": "HASH"
}
],
"ProvisionedThroughput": {
"ReadCapacityUnits": 5,
"WriteCapacityUnits": 5
}
}
Next, create an API Gateway REST API. Within that API, create a GET resource (e.g., /users/{userId}).
Now, for the magic: configure the GET method on this resource to integrate directly with DynamoDB.
-
Method Request:
- Under "Method Request," ensure the
userIdpath parameter is defined. This is crucial for passing the ID from the URL to DynamoDB.
- Under "Method Request," ensure the
-
Integration Request:
- Integration Type: Select "AWS Service."
- AWS Region: Choose the region where your DynamoDB table resides.
- AWS Service: Select "DynamoDB."
- HTTP Method: Choose "POST" (DynamoDB’s API for
GetItemis a POST request). - Action Type: Select "Use
x-amz-targetheader." x-amz-target: EnterDynamoDB_20120810.GetItem. This tells API Gateway which DynamoDB operation to call.- Request Body Passthrough: Uncheck this. We’ll define a custom passthrough.
- Request Transformation: This is where you map the incoming API request to the DynamoDB
GetItemAPI call. You’ll use a Velocity Template Language (VTL) template.
Here’s the VTL template for the
GET /users/{userId}method:{ "TableName": "users", "Key": { "userId": { "S": "$util.escapeJavaScript($input.params('userId'))" } } }TableName: Your DynamoDB table name.Key: This maps to theGetItemoperation’sKeyparameter.userId: Matches the primary key attribute name in your DynamoDB table."S": Specifies the data type of the attribute as String.$util.escapeJavaScript($input.params('userId')): This is the key part.$input.params('userId')extracts theuserIdfrom the path parameter you defined in the "Method Request."$util.escapeJavaScript()ensures that any special characters in theuserIdare properly escaped for JSON, preventing syntax errors.
-
IAM Permissions:
- API Gateway needs permission to call DynamoDB. You’ll need to create or update an IAM role for your API Gateway to assume. This role must have a policy that allows
dynamodb:GetItemon youruserstable.
Example IAM policy:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "dynamodb:GetItem" ], "Resource": "arn:aws:dynamodb:us-east-1:123456789012:table/users" } ] }(Replace
us-east-1and123456789012with your AWS region and account ID.) - API Gateway needs permission to call DynamoDB. You’ll need to create or update an IAM role for your API Gateway to assume. This role must have a policy that allows
-
Method Response:
- Configure the expected response from DynamoDB. For a successful
GetItem, DynamoDB returns a JSON object containing theItem. - You’ll likely want to map this DynamoDB
Itemback to a cleaner response for your API clients. In the "Integration Response," you can use another VTL template to transform the DynamoDB output.
Example VTL for mapping DynamoDB
Itemto a simpler response:#set($inputRoot = $input.path('$')) #set($output = {}) #set($output = $inputRoot.Item) $util.toJson($output)This VTL takes the
Itemfield from the DynamoDB response ($inputRoot.Item) and directly returns it. If you need to rename fields or select specific ones, you’d do more complex VTL here. - Configure the expected response from DynamoDB. For a successful
-
Deploy:
- Deploy your API to a stage (e.g.,
devorprod).
- Deploy your API to a stage (e.g.,
Now, if you make a GET request to https://your-api-id.execute-api.your-region.amazonaws.com/dev/users/user123, API Gateway will:
- Extract
user123from the path. - Construct a
GetItemrequest for DynamoDB using the VTL template. - Call the DynamoDB
GetItemAPI with the constructed request. - Receive the
Itemfrom DynamoDB. - Transform the
Itemusing the integration response VTL. - Return the final JSON response to the client.
This direct integration avoids the overhead of invoking and executing a Lambda function, reducing latency and cost for simple data retrieval or manipulation tasks. The VTL mapping is the critical piece, allowing you to translate the generic API Gateway request/response model into the specific DynamoDB API’s expectations.
The one thing most people don’t realize is that API Gateway’s VTL can directly access and manipulate the binary payload from AWS services when certain content types are configured, allowing for direct file uploads/downloads to S3 or even manipulating encrypted data with KMS before it hits the backend service.
The next step you’ll likely encounter is handling errors gracefully, like when a userId doesn’t exist in DynamoDB.