DynamoDB as a Serverless Service
While creating a Serverless application with multiple services, you might want to split the DynamoDB portion out separately. This can be useful because you are probably not going to be making changes to this very frequently. Also, if you have multiple development environments, it is not likely that you are going to connect them to different database environments. For example, you might give the developers on your team their own environment but they might all connect to the same DynamoDB environment. So it would make sense to configure DynamoDB separately from the application API services.
In the example repo, you’ll notice that we have a database
service in the services/
directory. And the serverless.yml
in this service helps us manage our DynamoDB table.
service: notes-app-mono-database
custom:
# Our stage is based on what is passed in when running serverless
# commands. Or fallsback to what we have set in the provider section.
stage: ${opt:stage, self:provider.stage}
# Set the table name here so we can use it while testing locally
tableName: ${self:custom.stage}-mono-notes
# Set our DynamoDB throughput for prod and all other non-prod stages.
tableThroughputs:
prod: 5
default: 1
tableThroughput: ${self:custom.tableThroughputs.${self:custom.stage}, self:custom.tableThroughputs.default}
provider:
name: aws
runtime: nodejs8.10
stage: dev
region: us-east-1
resources:
Resources:
NotesTable:
Type: AWS::DynamoDB::Table
Properties:
# Generate a name based on the stage
TableName: ${self:custom.tableName}
AttributeDefinitions:
- AttributeName: userId
AttributeType: S
- AttributeName: noteId
AttributeType: S
KeySchema:
- AttributeName: userId
KeyType: HASH
- AttributeName: noteId
KeyType: RANGE
# Set the capacity based on the stage
ProvisionedThroughput:
ReadCapacityUnits: ${self:custom.tableThroughput}
WriteCapacityUnits: ${self:custom.tableThroughput}
Outputs:
NotesTableArn:
Value:
Fn::GetAtt:
- NotesTable
- Arn
Export:
Name: ${self:custom.stage}-NotesTableArn
If you have followed along with Part II of our guide, the Resources:
section should seem familiar. It is creating the Notes table that we use in our note taking application. The key addition here in regards to the cross-stack references is in the Outputs:
section. Let’s go over them quickly.
-
We are exporting one value here. The
NotesTableArn
is the ARN of the DynamoDB table that we are creating. And theNotesTableName
which is the name of the table being created. The ARN is necessary for any IAM roles that are going to reference the DynamoDB table. -
The export name is based on the stage we are using to deploy this service -
${self:custom.stage}
. This is important because we want our entire application to be easily replicable across multiple stages. If we don’t include the stage name the exports will thrash when we deploy to multiple stages. -
The names of the exported values is
${self:custom.stage}-NotesTableArn
. -
We get the table ARN by using the
Fn::GetAtt
CloudFormation function. This function takes a reference from the current service and the attribute we need. The reference in this case isNotesTable
. You’ll notice that the table we created in theResources:
section is created usingNotesTable
as the name.
When we deploy this service we’ll notice the exported values in the output and we can reference these cross-stack in our other services.
Next we’ll do something similar for our S3 bucket.
For help and discussion
Comments on this chapterFor reference, here is the code we are using
Mono-repo Backend SourceIf you liked this post, please subscribe to our newsletter, give us a star on GitHub, and follow us on Twitter.