Using Amazon API Gateway as a proxy for DynamoDB in AWS CDK

Published on
Using Amazon API Gateway as a proxy for DynamoDB

Photo by dakmonk

Why use API Gateway as a proxy for AWS APIs?

Many AWS services provide APIs that applications depend on directly for their functionality. Examples include:

  1. Amazon DynamoDB – An API-accessible NoSQL database.
  2. Amazon Kinesis – Real-time ingestion of streaming data via API.
  3. Amazon CloudWatch – API-driven metrics collection and retrieval.

If AWS already exposes internet-accessible APIs, why would you want to use API Gateway as a proxy for them? Why not allow applications to just directly depend on the AWS service API itself?

Using Amazon API Gateway as a proxy for DynamoDB in AWS CDK

In this article, I will show you how to implement Amazon API Gateway as a proxy for DynamoDB by using AWS cdk. It is simpler than you think.

In this article we're going to create an Http API with 2 routes:

  • GET /posts/{id} get a post by ID
  • POST /posts create a post

CDK snippets

Creating the DynamoDB Table

const postTable = new dynamodb.Table(this, 'PostTable', {
  partitionKey: {
    name: 'id',
    type: dynamodb.AttributeType.STRING,
  removalPolicy: RemovalPolicy.DESTROY,
  billingMode: dynamodb.BillingMode.PAY_PER_REQUEST,

Creating the APIs

const api = new apigateway.RestApi(this, 'api-gateway-dynamodb', {
  description: 'Demo API Gateway with DynamoDB',
  // This will automatically set up OPTIONS responses for all your endpoints.
  defaultCorsPreflightOptions: {
    // allow all origins,
    allowOrigins: apigateway.Cors.ALL_ORIGINS,

Creating the Post API

const modelResource = api.root.addResource('posts')
// Create post
  new apigateway.AwsIntegration({
    service: 'dynamodb',
    action: 'PutItem',
    options: {
      credentialsRole: role,
      integrationResponses: [
          statusCode: '200',
          responseTemplates: {
            'application/json': `
                  "status": "OK"
      requestTemplates: {
        'application/json': `
            #set($inputRoot = $input.path('$'))
              "TableName": "${postTable.tableName}",
              "Item": {
                "id": {
                  "S": "$"
                "title": {
                  "S": "$inputRoot.title"
                "body": {
                  "S": "$inputRoot.body"
              "ConditionExpression": "attribute_not_exists(id)"

The code for this article is available on GitHub

Let's go over what we did in the code snippet.

  1. We create a proxy resource
  2. We added a route to our API. The route is for POST requests to /posts.

Let's deploy to test our API. We'll write the API url to a file on the local file system

npx aws-cdk deploy \
  --outputs-file ./cdk-outputs.json

That all, now you can test your api

Clean up

Don't forget clean all resource avoid unexpected cost.

npx cdk destroy