2 min read

Using DynamoDb with Serverless

I've been playing a lot with the Serverless framework since they moved from v0.x to v1 (which is currently in beta). I really like the direction they've taken it, and have been using it for my own projects.

One of the first things I wanted to do was hook my functions up to a data source: DynamoDb (DDB). While DDB is an obvious choice for a server-less application, keep in mind it's definitely not for all use-cases.

Here's a quick step by step guide to giving your Serverless Service DDB access:

Create Resources

Add the following snippet to the bottom of your serverless.yml file:

resources:
  Resources:
    DynamoDbTable:
      Type: AWS::DynamoDB::Table
      Properties:
        TableName: my-table
        AttributeDefinitions:
          - AttributeName: my_key
            AttributeType: S
        KeySchema:
          - AttributeName: my_key
            KeyType: HASH
        ProvisionedThroughput:
          ReadCapacityUnits: 5
          WriteCapacityUnits: 5
    DynamoDBIamPolicy:
      Type: AWS::IAM::Policy
      DependsOn: DynamoDbTable
      Properties:
        PolicyName: lambda-dynamodb
        PolicyDocument:
          Version: '2012-10-17'
          Statement:
            - Effect: Allow
              Action:
                - dynamodb:GetItem
                - dynamodb:PutItem
              Resource: arn:aws:dynamodb:*:*:table/my-table
        Roles:
          - Ref: IamRoleLambdaExecution

What this snippet is doing is creating additional AWS resources via a YAML-based representation of the CloudFormation definitions; A DDB Table and an IAM Policy.

DDB Table

The first resource is a DynamodDb table called DynamoDbTable (feel free to rename. Pick your own hash key, and change the provisioned throughput if you need to.

Other than the hash key, take note of the TableName parameter that you set, as this is what you'll reference in your function (there's a usage snippet below). Obviously change it (from "my-table") as you want.

IAM Policy

In order to give your Lambda function(s) access to the table, you'll need to give them permission through an IAM Policy. Make sure that the TableName you set in the DDB Table resource is updated in the Resource ARN in the statement (i.e. "...table/my-table").

The other interesting part of the IAM Policy snippet is the Ref: IamRoleLambda line at the end. IamRoleLambda is the name of the IAM Role given your Lambda functions by default in Serverless, so it assigns this policy to your functions.

In Your Function

Once you've deployed your Serverless service with the additional resources, you can reference it in your functions.

Here's an using the DynamoDb Document Client:

const AWS = require('aws-sdk');
const dynamo = new AWS.DynamoDB.DocumentClient();

...

module.exports.handler = (event, context, cb) => {
  ...
  const params = {
    TableName: 'my-table',
    Item: myItem,
  };
  ...
  return dynamo.put(params, cb);
};

Obviously you should update your table name value as needed. Remember the aws-sdk module is always available in Lambda, so you don't need to include it in your function bundle.

Variables

There's currently a PR under discussion, which might make it easier to reference things like the TableName value throughout your configuration dynamically (i.e. define it once in your serverless.yml), but it hasn't been merged at the time of writing.