--- title: Code, Deploy, and Manage a Serverless REST API on AWS h1: "Code, Deploy, and Manage a Serverless REST API on AWS with Pulumi" date: "2018-06-22" meta_desc: "In this post, we'll use Pulumi to create a simple serverless REST API using JavaScript to define both the infrastructure and application code." meta_image: "counter-arch.png" authors: ["donna-malayeri"] tags: ["JavaScript","Serverless","AWS"] --- Pulumi makes it easy to build serverless applications and connect to other cloud resources. In this blog post, we'll create a simple REST API that counts the number of times a route has been hit, using JavaScript to define both the infrastructure and application code. In Pulumi, you define your application infrastructure in regular code, using JavaScript, Python or Go, and you can target AWS, Azure, Google Cloud, or Kubernetes. The Pulumi command line tool transforms your into a declarative plan, following the best practices of immutable infrastructure. You can write your app code in any language supported by your serverless platform. ## Example app: serverless route counter In this tutorial, we'll build a simple REST API that counts the number of times a route has been hit. For example: $ curl $URL/wow {"route":"wow","count":1} $ curl $URL/pulumi {"route":"pulumi","count":1} $ curl $URL/wow {"route":"wow","count":2} We'll implement this using API Gateway, Lambda, and Dynamo DB: ![counter-arch](./counter-arch.png) ## Setup If this is your first time using Pulumi, go to and sign in with GitHub. Then, run the following command to install the Pulumi CLI: $ curl -fsSL https://get.pulumi.com/ | sh If you're on Windows, run this: @"%SystemRoot%System32WindowsPowerShell1.0powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "iex ((New-Object System.Net.WebClient).DownloadString('https://get.pulumi.com/install.ps1'))" SET "PATH=%PATH%;%USERPROFILE%.pulumiin" You'll deploy this app to your own AWS account, so follow the steps to [configure your AWS account](/docs/clouds/aws/get-started/). Make sure you have [Node.js](https://nodejs.org/en/download/) installed, with a version of 6.10.x or later. ## Create the App First we'll create a Pulumi project and add code for both the infrastructure definitions and application code. 1. To create a new Pulumi project, run the following commands: ``` {style="padding-left: 30px;"} mkdir hello-http && cd hello-http pulumi new aws-javascript ``` This creates a new project in the directory `hello-http`. 2. Replace the contents of `index.js` with the following: ``` {style="padding-left: 30px;"} const cloud = require("@pulumi/cloud-aws"); /* Create a mapping from 'route' to a count */ let counterTable = new cloud.Table("counterTable", "route"); /* Create an REST API endpoint */ let endpoint = new cloud.API("hello-world"); endpoint.get("/{route+}", (req, res) => { let route = req.params["route"]; console.log(`Getting count for '${route}'`); /* get previous value and increment */ /* reference outer counterTable object */ counterTable.get({ route }).then(value => { let count = (value && value.count) || 0; counterTable.insert({ route, count: ++count }).then(() => { res.status(200).json({ route, count }); console.log(`Got count ${count} for '${route}'`); }); }); }); exports.endpoint = endpoint.publish().url; ``` The definition for `counterTable` stores a counter for each route, using `cloud.Table`. On AWS, this provisions a DynamoDB instance. To create a new API Gateway instance, we create an instance of `cloud.API`. New routes can be added to this endpoint using functions such as `get`, `post`, `put` etc. The function passed to `get` is the interesting part: this becomes the body of a new AWS Lambda function that is called on a GET request to the API Gateway. The body of this function can use variables defined in the main program, such as `counterTable`. This is translated to a lookup on the provisioned DynamoDB instance; there is no need to store the table name in an environment variable. 3. Finally, add `@pulumi/cloud-aws` NPM package: ``` $ npm install --save @pulumi/cloud @pulumi/cloud-aws ``` ## Deploy the App To deploy both the infrastructure and app code, we'll run `pulumi update`. This command first shows a preview of all the resources that will be created and prompts for confirmation. ![pulumi-update-preview](./pulumi-update-preview.png) Choose the "yes" option to deploy to AWS. At the end of the update, you'll see a link to the Pulumi Service that shows the details of the deployment. ![pulumi-update-complete](./pulumi-update-complete.png) Go to this link and click the **Resources** tab. You'll see all the resources you've created, including links to the AWS Console. ![console-resources-tab](./console-resources-tab.png) ## Test the App Now that the app is deployed, let's try it out! With the Pulumi CLI, you can easily view output properties for your stack. This line in the JavaScript code creates a **stack output**. ```javascript exports.endpoint = endpoint.publish().url; ``` You can view stack outputs in the Pulumi Service, or via `pulumi stack output`: $ pulumi stack output Current stack outputs (1): OUTPUT VALUE endpoint https://5e8xrktey3.execute-api.us-west-2.amazonaws.com/stage/ Now, let's curl some routes! $ curl $(pulumi stack output endpoint)/wow {"route":"wow","count":1} $ curl $(pulumi stack output endpoint)/pulumi {"route":"pulumi","count":1} $ curl $(pulumi stack output endpoint)/wow {"route":"wow","count":2} You can also view logs for the Lambda via `pulumi logs`. To get a log tail, use the `--follow` or `-f` flag: $ pulumi logs Collecting logs for stack hello-http-dev since 2018-06-15T12:53:35.000-07:00. 2018-06-15T13:52:30.123-07:00[ hello-world4fcc7b60] Getting count for 'wow' 2018-06-15T13:52:34.361-07:00[ hello-world4fcc7b60] Got count 1 for 'wow' 2018-06-15T13:52:39.621-07:00[ hello-world4fcc7b60] Getting count for 'pulumi' 2018-06-15T13:52:39.757-07:00[ hello-world4fcc7b60] Got count 1 for 'pulumi' 2018-06-15T13:52:42.189-07:00[ hello-world4fcc7b60] Getting count for 'wow' 2018-06-15T13:52:42.325-07:00[ hello-world4fcc7b60] Got count 2 for 'wow' ## Clean up To clean up the resources, run `pulumi destroy`. ## Next steps The [sample code for this application](https://github.com/pulumi/examples/tree/master/cloud-js-httpserver) is available in the Pulumi examples repo on GitHub. For an end-to-end TypeScript application with a frontend, see the [URL shortener sample](https://github.com/pulumi/examples/tree/master/cloud-ts-url-shortener).