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 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.

Click through for source

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.

Click through for source

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.


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 ๐Ÿ˜‡

Click through for source

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.

Click through for source

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 ๐Ÿ˜…


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 ๐Ÿ‘‡

Click through for source

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.

Click through for source

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 ๐Ÿ‘‡

Click through for source

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 โค๏ธ,

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

Learned something new? Want to improve your skills?

Join over 10,000 engineers just like you already improving their skills!

Here's how it works ๐Ÿ‘‡

Leave your email and I'll send you an Interactive Modern JavaScript Cheatsheet ๐Ÿ“–right away. After that you'll get thoughtfully written emails every week about React, JavaScript, and your career. Lessons learned over my 20 years in the industry working with companies ranging from tiny startups to Fortune5 behemoths.

PS: You should also follow me on twitter ๐Ÿ‘‰ here.
It's where I go to shoot the shit about programming.