https://github.com/davicedraz/serverless-visit-counter
Experimental Serverless Node.js Express API
https://github.com/davicedraz/serverless-visit-counter
aws-lambda clean-architecture dynamodb nodejs serverless
Last synced: 3 days ago
JSON representation
Experimental Serverless Node.js Express API
- Host: GitHub
- URL: https://github.com/davicedraz/serverless-visit-counter
- Owner: davicedraz
- Created: 2021-05-22T22:18:22.000Z (almost 5 years ago)
- Default Branch: master
- Last Pushed: 2021-05-24T17:30:53.000Z (almost 5 years ago)
- Last Synced: 2025-01-03T11:12:51.752Z (over 1 year ago)
- Topics: aws-lambda, clean-architecture, dynamodb, nodejs, serverless
- Language: JavaScript
- Homepage:
- Size: 618 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
## Serverless Node Express API
This project it is being developed to apply serverless concepts using Node.js, the [Serverless](https://www.serverless.com/) framework and AWS platform (Lambda functions).
This a simples API that communicates with the free service [CountAPI](https://countapi.xyz/). This API allows you to create simple numeric counters IaaS (Integer as a Service) and increment/decrement it. This counter will be used to store the number of hits from a website.
API features:
- [x] Increase the number of accesses
- [x] Consult the number of accesses
- [x] Create a user
- [x] View a user's information
- [ ] Increment the hit counter automatically when the site is visited
- [ ] Create a new hit counter when a logged in user visits the site
### Architecture
This project takes advantage of [Services Pattern](https://www.serverless.com/blog/serverless-architecture-code-patterns), where a single Lambda function can handle a few (~4) jobs that are usually related via a data model or a shared infrastructure dependency. In our example app, all operations on the Users data model are performed in a single Lambda function, and multiple HTTP endpoints are created for all CRUD operations.
Benefits of Services Pattern:
- This will result in less Lambda functions that you need to manage.
- Some separation of concerns still exists.
- Teams can still work autonomously.
- Faster deployments.
- Theoretically better performance. When multiple jobs are within a Lambda function, there is a higher likelihood that Lambda function will be called more regularly, which means the Lambda will stay warm and users will run into less cold-starts.
Drawbacks of Services Pattern:
- Debugging gets slightly more complicated, since the Lambda function is handling multiple jobs, and has different outcomes.
- Requires creating a router to call the right logic based on the request method or endpoint.
- Bigger function sizes due to putting multiple operations within the same Lambda function.

### Project Structure
When we consider DevOps frameworks like [serverless](https://www.serverless.com/) Framework, it expects to point each route to a separate Lambda function. But this project exposes one single function, `api`, in `serverless.yml` which is responsible for handling all incoming requests thanks to configured `http` events. To learn more about `http` event configuration options, please refer to [http event docs](https://www.serverless.com/framework/docs/providers/aws/events/apigateway/). As the events are configured in a way to accept all incoming requests, `express` framework is responsible for routing and handling requests internally. Implementation takes advantage of `serverless-http` package, which allows you to wrap existing `express` applications. To learn more about `serverless-http`, please refer to corresponding [GitHub repository](https://github.com/dougmoscrop/serverless-http). Additionally, it also handles provisioning of a DynamoDB database that is used for storing data about users. The `express` application exposes two endpoints, `POST /users` and `GET /user/{userId}`, which allow to create and retrieve users.
### Deployment
This example is made to work with the Serverless Framework dashboard, which includes advanced features such as CI/CD, monitoring, metrics, etc.
In order to deploy with dashboard, you need to first login with:
```
serverless login
```
install dependencies with:
```
npm install
```
and then perform deployment with:
```
serverless deploy
```
After running deploy, you should see output similar to:
```bash
Serverless: Packaging service...
Serverless: Excluding development dependencies...
Serverless: Creating Stack...
Serverless: Checking Stack create progress...
........
Serverless: Stack create finished...
Serverless: Uploading CloudFormation file to S3...
Serverless: Uploading artifacts...
Serverless: Uploading service aws-node-express-dynamodb-api.zip file to S3 (718.53 KB)...
Serverless: Validating template...
Serverless: Updating Stack...
Serverless: Checking Stack update progress...
....................................
Serverless: Stack update finished...
Service Information
service: aws-node-express-dynamodb-api
stage: dev
region: us-east-1
stack: aws-node-express-dynamodb-api-dev
resources: 13
api keys:
None
endpoints:
ANY - https://xxxxxxx.execute-api.us-east-1.amazonaws.com/dev/
ANY - https://xxxxxxx.execute-api.us-east-1.amazonaws.com/dev/{proxy+}
functions:
api: aws-node-express-dynamodb-api-dev-api
layers:
None
```
### Local development
It is also possible to emulate DynamodB, API Gateway and Lambda locally by using `serverless-dynamodb-local` and `serverless-offline` plugins. In order to do that, execute the following commands:
```bash
serverless plugin install -n serverless-dynamodb-local
serverless plugin install -n serverless-offline
```
It will add both plugins to `devDependencies` in `package.json` file as well as will add it to `plugins` in `serverless.yml`. Make sure that `serverless-offline` is listed as last plugin in `plugins` section:
```
plugins:
- serverless-dynamodb-local
- serverless-offline
```
You should also add the following config to `custom` section in `serverless.yml`:
```
custom:
(...)
dynamodb:
start:
migrate: true
stages:
- dev
```

Additionally, we need to reconfigure `AWS.DynamoDB.DocumentClient` to connect to our local instance of DynamoDB. We can take advantage of `IS_OFFLINE` environment variable set by `serverless-offline` plugin and replace:
```javascript
const dynamoDbClient = new AWS.DynamoDB.DocumentClient();
```
with the following:
```javascript
const dynamoDbClientParams = {};
if (process.env.IS_OFFLINE) {
dynamoDbClientParams.region = 'localhost'
dynamoDbClientParams.endpoint = 'http://localhost:8000'
}
const dynamoDbClient = new AWS.DynamoDB.DocumentClient(dynamoDbClientParams);
```
After that, running the following command with start both local API Gateway emulator as well as local instance of emulated DynamoDB:
```bash
serverless offline start
```
To learn more about the capabilities of `serverless-offline` and `serverless-dynamodb-local`, please refer to their corresponding GitHub repositories:
- https://github.com/dherault/serverless-offline
- https://github.com/99x/serverless-dynamodb-local