https://github.com/seriousme/docker-voting-app-aws
Docker Voting App done Serverless Style using AWS
https://github.com/seriousme/docker-voting-app-aws
api-gateway aws-dynamodb serverless
Last synced: 2 months ago
JSON representation
Docker Voting App done Serverless Style using AWS
- Host: GitHub
- URL: https://github.com/seriousme/docker-voting-app-aws
- Owner: seriousme
- Created: 2018-03-21T20:07:51.000Z (about 8 years ago)
- Default Branch: master
- Last Pushed: 2024-01-27T17:35:58.000Z (about 2 years ago)
- Last Synced: 2025-05-17T13:09:38.545Z (11 months ago)
- Topics: api-gateway, aws-dynamodb, serverless
- Homepage:
- Size: 271 KB
- Stars: 3
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Docker Voting App done Serverless Style
[](https://console.aws.amazon.com/cloudformation/home?#/stacks/new?stackName=ServerlessVotingApp&templateURL=https://cf-templates-dxlmf2isjd8s-eu-west-1.s3-eu-west-1.amazonaws.com/2019255sNG-voteApp-CF-template.json)
## Introduction
I was reading [Deploy the Voting App to AWS ECS with Fargate] by Tony Pujals
where he describes how to run the [Docker Voting app demo] on AWS using [AWS
Fargate]
[deploy the voting app to aws ecs with fargate]: https://medium.com/@tonypujals/deploy-the-voting-app-to-aws-ecs-with-fargate-
[docker voting app demo]: https://github.com/subfuzion/docker-voting-app-nodejs
[aws fargate]: https://aws.amazon.com/fargate/
Of course I understand that the Docker Voting app is a showcase of Docker
technology and that it's not the most exciting application from a business
perspective. I also understand that people want to show how you can take Docker
technology to AWS. However in my mind I started wondering: if I would take this
to AWS would I be following the same path ? Or would I go Serverless ?
Given the title: I went Serverless!
The voting application is recreated using AWS ApiGateway and AWS DynamoDB only.
The queue service could be implemented using SNS, however one typically uses a
queue to ensure scalability of the database or to allow for maintenance. Both
are handled by AWS DynamoDB automatically.

## Creating the schema
Looking at the sources of the voting app there are two endpoints:
* POST /vote where you can post a vote by posting JSON like `{"vote":"a"}` or
`{"vote":"b"}`
* GET /results which will give you results like:
```json
{
"success": true,
"result": {
"a": 0,
"b": 0
}
}
```
Creating a JSON schema produces the following for /vote
```json
{
"Vote": {
"type": "object",
"required": ["vote"],
"properties": {
"vote": {
"type": "string",
"enum": ["a", "b"]
}
},
"title": "Vote Schema"
}
}
```
and for /results
```json
{
"type": "object",
"properties": {
"success": {
"type": "boolean"
},
"result": {
"type": "object",
"properties": {
"a": {
"type": "integer"
},
"b": {
"type": "integer"
}
}
}
},
"title": "Results schema"
}
```
Loading these in APIgateway ensures for /vote that only valid POST requests are
accepted.
## DynamoDB
The DynamoDB instance with partion key `topic` only holds one record with
`topic` value `default` and a numeric value for `a` and `b`
## APIgateway integration
A succesful POST operation must result in a increment of the counter for the
subject of the vote in the database. This is achieved by adding the following
integration request mapping template to the POST operation:
```json
{
"TableName": "VoteAppDynamoDBTable",
"Key": {
"topic": {
"S": "default"
}
},
"UpdateExpression": "ADD $input.path('$.vote') :inc",
"ExpressionAttributeValues": {
":inc": {
"N": "1"
}
}
}
```
This, together with the rest of the integration configuration, will transform
the POST operation into a call to DynamoDB to increment the number of votes for
the subject provided.
Then when pulling results the GET operation needs to be transformed into a query
on DynamoDB using an integration request mapping template
```json
{
"TableName": "VoteAppDynamoDBTable",
"KeyConditionExpression": "topic = :v1",
"ExpressionAttributeValues": {
":v1": {
"S": "default"
}
}
}
```
and the response needs to be mapped to the schema listed above using an
integration response mapping template
```
#set($inputRoot = $input.path('$'))
{
"success" : true,
"result" : {
#if($inputRoot.Count==0)
"a" : 0,
"b" : 0
#{else}
"a" : #if($inputRoot.Items[0].a=="")0#{else}$inputRoot.Items[0].a.N#end,
"b" : #if($inputRoot.Items[0].b=="")0#{else}$inputRoot.Items[0].b.N#end
#end
}
}
```
As long as no votes have been casted it could be that the whole record does not
exist yet or that `a` or `b` is still non-existent. This template takes care of
these edge cases.
The full AWS Cloudformation template can be found [here]. There is also a
[version using Google Firebase].
[here]: voteApp-CF-template.
[version using google firebase]: https://github.com/seriousme/docker-voting-app-gcp