Big News! Split to be acquired by Harness. Read More

Serverless Express & TypeScript Application With AWS Lambda


Split - BuildingAServerlessExpressandTypescriptApplication-2

Serverless architecture has become increasingly popular due to its cost-effectiveness and scalability. Using services such as AWS Lambda, developers can build and deploy their applications without needing servers or infrastructure. In this blog post, you’ll learn how to make a serverless Express and TypeScript application using AWS Lambda and API Gateway.

Express is an infamous Node.js framework that simplifies building web applications. TypeScript, on the other hand, is a typed superset of JavaScript that can be transferred to plain JavaScript and run in any browser or JavaScript environment. Together, these technologies make creating robust and scalable web applications accessible.

What’s AWS Lambda? It’s a service that allows you to run your code without provisioning or managing servers. With AWS Lambda, you only pay for your computing time and don’t need to worry about scaling or maintaining servers.

Let’s also tackle API Gateway! This is a service that allows you to create, publish, and manage APIs. The benefit of an API Gateway is that it can create a RESTful API for your Lambda function, which a web or mobile application can consume.

Today, we’ll cover a few different topics with code examples for each. Here’s what we’ll be diving into.

  1. Setting up the development environment
  2. Creating a new Express and TypeScript application
  3. Configuring AWS Lambda and API Gateway
  4. Deploying the application to AWS
  5. Testing and debugging the application
  6. Conclusion and next steps

By the end of this tutorial, the hope is to have a fully-functioning serverless Express and TypeScript application running on AWS Lambda and API Gateway. Let’s get started, shall we?

Setting up the Development Environment

Before You can begin building a serverless Express and TypeScript application, you need to set up a development environment. Start by installing Node.js, TypeScript, and the AWS CLI (if you don’t already have them).

When installing Node.js, download the installer from the official website and follow the instructions. Once it’s on your machine, be sure to check the version by running the following command in your terminal:

node -v

Next, you need to install TypeScript. You can run the following command:

npm install -g typescript

This will install TypeScript globally on your machine. You can check the version by running the following:

tsc -v

Finally, you need to install the AWS CLI. You can do this by running the following command:

npm install -g aws-cli

Once the AWS CLI is installed, you will need to configure it with your AWS credentials. You can do this by running the following command:

aws configure

After you’ve entered the code, you’ll be prompted you to enter your AWS access key, secret key, and the region you want to use. Hopefully you’ve got it written down (or it’s filed somewhere safe in your noggin).

Type it in, and you should be off to the races!

Creating a New Express and TypeScript Application

Okay, so you’re development environment is ready—that’s great news! Now let’s start creating your new Express and TypeScript application. The first thing you’ll need to do is create a fresh directory. Specify it for your project and navigate right there:

mkdir serverless-express-ts && cd serverless-express-ts

Next, you’ll initialize our project with npm:

npm init -y

This step will create a package.json file in your project directory containing your application’s dependencies and scripts.

Next, install the necessary dependencies for your project. These include express, @types/express, and ts-node. Here’s what that code looks like:

npm install express @types/express ts-node --save-dev

Next, create an src directory to hold our TypeScript files and a src/app.ts file, which will be the entry point for our application. You’ll need to create a tsconfig.json file in the root of our project, which will configure TypeScript for our application:

mkdir src && touch src/app.ts && touch tsconfig.json

The tsconfig.json file should contain the following:

// tsconfig.json
  "compilerOptions": {
    "module": "commonjs",
    "esModuleInterop": true,
    "target": "es6",
    "noImplicitAny": true,
    "moduleResolution": "node",
    "sourceMap": true,
    "outDir": "dist",
    "baseUrl": ".",
    "paths": {
      "*": ["node_modules/*"]
  "include": ["src/**/*"]

Now add a simple Express application to our src/app.ts file:

// src/app.ts
import express from "express";

const app = express();

app.get("/", (req, res) => {
  res.send("Hello World!");

app.listen(3000, () => {
  console.log("Server started on http://localhost:3000");

Notice how this simple Express application listens on port 3000. It should return a “Hello World!” message once the root route is accessed. What a friendly greeting!

You can then run this application, but you must add a script to our package.json file. Call this script start, and it will use ts-node to run our src/app.ts file:

// package.json
  "scripts": {
    "start": "ts-node src/app.ts"

Now you can start the application by running:

npm start

You should see the message: Server started on http://localhost:3000 in your terminal. At this point, you can access your application by navigating to http://localhost:3000 in your browser.

With a working Express and TypeScript application, you can proceed to the next step of configuring AWS Lambda and API Gateway.

It’s worth noting that there aren’t any test or build scripts in this example. However, it’s still best practices to keep them in a real-world project. You could always use other tools like webpack or babel to transpile and bundle your production application. Options do exist!

It’s also worth noting that this example assumes you have the AWS CLI installed and configured on your machine. If you haven’t done that already, you’ll need to make it happen before proceeding to the next step.

Now that you’ve walke through those steps, you’re ready to configure AWS Lambda and API Gateway to run our serverless application—boom!

Configuring AWS Lambda and API Gateway

Let’s dig in!

First, you’ll need to create a new AWS Lambda function. You can do this using the AWS CLI by running the following command:

aws lambda create-function --function-name serverless-express-ts --runtime nodejs12.x --handler dist/app.handler --role arn:aws:iam::<ACCOUNT_ID>:role/<ROLE_NAME> --zip-file fileb://dist/

After punching in that command, a new Lambda function named serverless-express-ts should pop it. Notice the runtime of Node.js 12.x, using the dist/app.handler file as the handler and the dist/ file as the deployment package. The role flag is used to specify the IAM role that the function will use. Be sure to replace and with your own.

Next, let’s create a new API Gateway by running the following command:

aws apigateway create-rest-api --name "Serverless Express TS"

This command creates a new REST API named “Serverless Express TS”. You should see the id of the created API in the response. Now you’ll create a new resource for the API:

aws apigateway create-resource --rest-api-id <API_ID> --parent-id <ROOT_RESOURCE_ID> --path-part "{proxy+}"

That code creates a new resource named {proxy+} and sets it up as a child of the root resource. Now go ahead and replace and with the appropriate values from the previous step.

After that, create a new method for the resource. Here’s how:

aws apigateway put-method --rest-api-id <API_ID> --resource-id <RESOURCE_ID> --http-method ANY --authorization-type NONE

This command creates a new method for the resource. One that accepts any HTTP method and does not require authorization. Always replace and with the appropriate values from the previous step.

Here’s how to create the integration for this method:

aws apigateway put-integration --rest-api-id <API_ID> --resource-id <RESOURCE_ID> --http-method ANY --type AWS --integration-http-method ANY --uri arn:aws:apigateway:<REGION>:lambda:path/2015-03-31/functions/arn:aws:lambda:<REGION>:<ACCOUNT_ID>:function:serverless-express-ts/invocations

This command creates an integration between the method and the Lambda function you created earlier, using the ANY HTTP method and allowing the Lambda function to be invoked using the ANY HTTP method. Replace <API_ID>, <RESOURCE_ID>, <REGION>, and <ACCOUNT_ID> with the appropriate values.

Okay, almost done. As a final step, you’ll now deploy the API:

aws apigateway create-deployment --rest-api-id <API_ID> --stage-name prod

Notice how it deploys the API to a new stage named “prod”. Be ready to replace <API_ID> with the appropriate value and—wallah! You have successfully configured AWS Lambda and API Gateway to run a serverless Express and TypeScript application.

You can now test the API by sending a request to the endpoint provided in the response of the create-deployment command.

The above code examples are a basic setup for running an Express application on AWS Lambda and API Gateway. Depending on your specific use case, you may need to add additional resources, methods, and integrations to utilize the services’ capabilities in fully. Don’t be shy about using the serverless framework to automate the deployment process, making things even more efficient.

Deploying the application to AWS

Now for the grand finale of building a serverless Express and TypeScript application with AWS and Lamda! It’s all about deploying the application to AWS!

The process involves packaging the application code and dependencies and uploading it to AWS Lambda.

To deploy the application, you must have the AWS CLI installed and configured on your machine. Once that’s done, use the aws lambda create-function command to create a new AWS Lambda function. Take this junction to reach that function:

aws lambda create-function \
    --function-name my-express-app \
    --runtime nodejs14.x \
    --role <ROLE_ARN> \
    --handler index.handler \
    --zip-file fileb://path/to/

There you have it. A new function named my-express-app is created with the runtime set to Node.js 14.x. Replace <ROLE_ARN> with the ARN of the IAM role that you created earlier. Set the handler parameter is to index.handler, the default handler for an Express application. The zip-file parameter should also be set to the path of the deployment package, which is a zip file containing the code and dependencies.

Don’t forget to use the aws lambda update-function-code command to update the code:

aws lambda update-function-code \
    --function-name my-express-app \
    --zip-file fileb://path/to/

After the function is created, test it by sending a test event to it using the aws lambda invoke command. Here it is:

aws lambda invoke \
    --function-name my-express-app \
    --payload '{"httpMethod": "GET", "path": "/"}' \
    --log-type Tail \

This will invoke the function and send the test event payload to it. The response of the function will be written to the response.json file. The log-type parameter should be set to Tail, which means that the last 4 KB of the log stream will be returned in the response.

Prop tip: You can also use the AWS Management Console to deploy your code, and this can be done by going to the AWS Lambda service. Once you’ve done that, find your function and upload your code from there.

Now you’re live on AWS Lambda and ready to go!

Testing and Debugging a Serverless Express and TypeScript Application

Okay, wait just one second! You can’t call it a day until you check your application for bugs. Luckily, you can quickly test and debug your application on AWS Lambda with the right tools and techniques.

One way to test your application is by using the AWS CLI to invoke the function and inspect the response.

Another way to test your application is by using the AWS Management Console. In the AWS Lambda service, quickly locate your function and then test it using the built-in test function; this will allow you to simulate different input events to your function and monitor the results for bugs.

AWS Lambda automatically generates logs for each invocation of a function. You can view these logs in the CloudWatch service. And, if your function is not working as expected, you can always use the logs generated by AWS Lambda to debug the issue.

Here’s another option: Use the console.log() statement to print debug information to the logs. To view the logs, you can use the aws logs filter-log-events command. Like this:

aws logs filter-log-events \
    --log-group-name /aws/lambda/my-express-app \
    --start-time <START_TIME> \
    --end-time <END_TIME>

That should return all the log events for the specified log group between the start and end time.

As an alternate strategy, you can choose to debug your application by using breakpoints; AWS Lambda supports debugging your code using the AWS Toolkit for Visual Studio Code. Go in to set up breakpoints, step through the code, inspect variables, and quickly identify, and fix any issues.

That’s if for now. We hope these steps we’re helpful and the commands got you what you needed.

Switch It On With Split

The Split Feature Data Platform™ gives you the confidence to move fast without breaking things. Set up feature flags and safely deploy to production, controlling who sees which features and when. Connect every flag to contextual data, so you can know if your features are making things better or worse and act without hesitation. Effortlessly conduct feature experiments like A/B tests without slowing down. Whether you’re looking to increase your releases, to decrease your MTTR, or to ignite your dev team without burning them out–Split is both a feature management platform and partnership to revolutionize the way the work gets done. Schedule a demo to learn more.

Get Split Certified

Split Arcade includes product explainer videos, clickable product tutorials, manipulatable code examples, and interactive challenges.

Want to Dive Deeper?

We have a lot to explore that can help you understand feature flags. Learn more about benefits, use cases, and real world applications that you can try.

Code"}]}" data-page="1" data-max-pages="1">

Create Impact With Everything You Build

We’re excited to accompany you on your journey as you build faster, release safer, and launch impactful products.