Swizec Teller - a geek with a hatswizec.com

Senior Mindset Book

Get promoted, earn a bigger salary, work for top companies

Senior Engineer Mindset cover
Learn more

    TypeScript for serverless lambda backends πŸ‘Œ

    A few months ago I inherited a Kotlin project. It was an unfinished prototype and all I had to do was wrap it up and deploy.

    How hard can it be?

    Weeks passed. Even months.

    Every time I touched the project, it broke. Nothing worked. Wouldn't run on my machine, wouldn't read API requests, couldn't get tests working, if I changed some code I broke it all.

    That's when I realized Learning a new field is super hard πŸ˜…

    Tried to look for help online and ... nothing. The Kotlin community just doesn't seem to exist. There's no gaggle of blogs, no quality courses, there's a few books but everything is for Android.

    I'm using Kotlin for the backend damn it, why do I feel so alone?

    With no community to be found there's only one conclusion πŸ‘‰ I'm forcing Kotlin to do something it doesn't want to do. Or Kotlin is weird and on its way out.

    Hell, it was easier to find LOLCODE resources for that LOLCODE-to-JavaScript compiler the other day ...

    screw_this giphy

    So I said screw it and got the whole project working in TypeScript in 3 days. ✌️

    Why Kotlin? Why TypeScript?

    A good question at this point: Why did we even try Kotlin in the first place?

    There's a lot of backstory, but it's all about solving these problems πŸ‘‡

    • we have a Ruby on Rails backend
    • it is slow
    • parts of the system are struggling under load
    • dynamic typing leads to bugs

    We wanted to extract the most impacted subsystem. Build it so that it's fast, reliable, and easy for many developers to work with. And isolated from the rest of our monolith.

    You can get speed and reliability with AWS Lambdas. You can get type safety with Java. And Java is a very popular language on the backend.

    But Java is hard to use and annoying to write.

    Kotlin seemed like a great alternative. Runs on the Java Virtual Machine (JVM), interops with Java, and supports many modern functional idioms. Plus it's fast because the JVM is fast.

    Except nobody on the team knows Kotlin.

    πŸ˜…

    But we're smart, we can learn this! And we sort of did.

    Until both the person leading the lets-move-to-JVM charge left the company and his I-love-doing-backend protege left us for a career at Google.

    Backend people are a special breed, they all seem to love Java and Java-like things so much.

    shrug giphy

    So here I was with this unfinished prototype, no skills in Kotlin, a deep seated distrust of all things Java from college, and an open deadline. Get it working when you can, nothing's on fire right now.

    I tried. I did my best. I gave up.

    TypeScript!

    TypeScript solves our problems, works great with AWS Lambdas, and the whole team knows at least JavaScript.

    TypeScript with AWS Lambda πŸ‘‡

    • super fast because your code is small
    • faster cold start times than Kotlin
    • type safety for robustness

    You see the thing with AWS Lambda is that you are charged for time. Faster is cheaper, and while JVM functions run faster, node functions start faster.

    Our functions are small so runtimes are small. But those cold starts can add up since most Lambda calls are cold. It's a new computer almost every time :)

    Engineering is all about tradeoffs

    How to use TypeScript for AWS Lambdas

    So how do you use TypeScript to write an AWS Lambda function?

    Let's write a Hello World function. I'm extracting this from my real code and haven't tested it. Think of this code as a guide, not a copypasta.

    pirate_code giphy

    You start by installing the TypeScript compiler. You'll need node support too.

    $ npm install -g typescript ts-node
    

    You can now write TypeScript programs and compile them with tsc so node can run them. Yes you'll need to compile every time before running.

    But you already do that for your frontend code anyway :)

    You're also going to need the Serverless framework.

    $ npm install -g serverless
    

    At this point it's a good idea to open a new terminal window so the new CLI commands register.

    Oh and you should setup serverless AWS credentials. It's a little tedious, but you only gotta do it once for all your projects.

    tsconfig.json

    Before you can seamlessly compile the whole project, you need to configure TypeScript. I copypasta'd this JSON from a blogpost and it works great. Sensible defaults I'd say πŸ˜‡

    {
    	"compilerOptions": {
    		"target": "es2017",
    		"module": "commonjs",
    		"outDir": "./dist",
    		"strict": true,
    		"baseUrl": "./",
    		"typeRoots": [
    			"node_modules/@types"
    		],
    		"types": [
    			"node"
    		],
    		"esModuleInterop": true,
    		"inlineSourceMap": true
    	}
    }
    

    This tells the TypeScript compiler that you're targeting es2017 – the latest JavaScript standard supported by Node 8.10, which is the latest Node that AWS supports. You're using commonjs modules, writing compiled files to ./dist and so on.

    tsconfig.json supports many options but you aren't likely to need them. At least not at first.

    The package.json

    Next we'll need a package.json file with some scripts. These will help you build and deploy your code.

    {
    	"name": "hello-world-lambda",
    	"scripts": {
    		"build": "tsc",
    		"deploy": "npm run build && sls deploy"
    	}
    }
    

    We run tsc to build the project, and sls deploy to deploy. Adding the build step to your deploy script makes it less likely that you'll forget to build before deploying.

    Always important to deploy the latest code. Gets very frustrating if you don't πŸ˜…

    serverless.yml

    We use serverless.yml to configure the Serverless framework. Using this file means you:

    • never have to deal with the UI on AWS (or Azure or whatever)
    • keep your system architecture in source control
    • can reliably build the same server environment every time

    Might seem weird at first, but once you get used to all your infrastructure being part of your code ... wow. It's like a whole new world.

    Our Hello World example doesn't need much πŸ‘‡

    service: hello-world
    
    provider:
    	name: aws
    	runtime: nodejs8.10
    	stage: dev
    	
    	functions:
    		hello:
    			handler: dist/hello.handler
    			events:
    				- http:
    						path: hello
    						method: GET
    						cors: true
    

    With that you've configured:

    • an AWS Lambda function called hello
    • an APIGateway to proxy API requests
    • a CloudWatch setup for any logs

    Yep. All that in those few lines of Yaml. Once you deploy Serverless will give you the URL for your hello function.

    But first you gotta write it

    The hello function – src/hello.ts

    Before you write the function, there's a couple dependencies I'd recommend. They make TypeScript work smoother with node and AWS.

    $ npm install --save @types/aws-lambda @types/node typescript
    

    I'm not sure the typescript dependency is strictly necessary, but I have it. The two @types dependencies give you type information for built-in stuff.

    Your hello world function looks like this πŸ‘‡

    // src/hello.ts
    
    import { APIGatewayEvent } from "aws-lambda";
    
    export const handler = async (event: APIGatewayEvent): Promise<any> => {
    	return {
    		statusCode: 200,
    		body: "Hello world"
    	}
    }
    

    And that's it.

    You're importing the type definition for the APIGatewayEvent. That specifies which properties it does and doesn't have, gives you code completion, and helpful tooltips in VS Code.

    To make an endpoint, you export a function. Often called handler but can be anything. You specified the exact name in your serverless.yml earlier (handler: dist/hello.handler).

    This function takes an event, does whatever it wants, and returns a response with a statusCode and a body. 200 means OK.

    You can run npm run deploy, wait a bit, and voila you've got a URL that says Hello World πŸ‘Œ

    That's what I love about this new function-as-a-service world. Anyone can build a backend. A good backend. Not just those Java-toting backend weirdos.

    Happy Monday ❀️,
    ~Swizec

    PS: if you wanna read more about my initial impressions of TypeScript, you should check out this twitter thread

    Published on May 27th, 2019 in Backend Web, Serverless, Technical

    Did you enjoy this article?

    Continue reading about TypeScript for serverless lambda backends πŸ‘Œ

    Semantically similar articles hand-picked by GPT-4

    Senior Mindset Book

    Get promoted, earn a bigger salary, work for top companies

    Learn more

    Have a burning question that you think I can answer? Hit me up on twitter and I'll do my best.

    Who am I and who do I help? I'm Swizec Teller and I turn coders into engineers with "Raw and honest from the heart!" writing. No bullshit. Real insights into the career and skills of a modern software engineer.

    Want to become a true senior engineer? Take ownership, have autonomy, and be a force multiplier on your team. The Senior Engineer Mindset ebook can help πŸ‘‰ swizec.com/senior-mindset. These are the shifts in mindset that unlocked my career.

    Curious about Serverless and the modern backend? Check out Serverless Handbook, for frontend engineers πŸ‘‰ ServerlessHandbook.dev

    Want to Stop copy pasting D3 examples and create data visualizations of your own? Learn how to build scalable dataviz React components your whole team can understand with React for Data Visualization

    Want to get my best emails on JavaScript, React, Serverless, Fullstack Web, or Indie Hacking? Check out swizec.com/collections

    Did someone amazing share this letter with you? Wonderful! You can sign up for my weekly letters for software engineers on their path to greatness, here: swizec.com/blog

    Want to brush up on your modern JavaScript syntax? Check out my interactive cheatsheet: es6cheatsheet.com

    By the way, just in case no one has told you it yet today: I love and appreciate you for who you are ❀️

    Created by Swizec with ❀️