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?
The time has come for me to learn Kotlin. Because reasons
First surprise: It takes 700MB of space just to install the language. No IDE or anything.
node_modules ain't got nothing on this
— Swizec Teller (@Swizec) March 5, 2019
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.
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.
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.
So I finally forced myself to write some TypeScript for real and I don't hate it. 🤨
Greenfield backend project so I was able to avoid `any` like the plague. That helped a bunch in making TS make sense.
Here's things I liked and things I didn't 👇
— Swizec Teller (@Swizec) May 25, 2019
TypeScript with AWS Lambda 👇
- super fast because your code is small
- faster cold start times than Kotlin
- type safety for robustness
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.
You start by installing the TypeScript compiler. You’ll need node support too.
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.
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 😇
This tells the TypeScript compiler that you’re targeting
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.
Next we’ll need a package.json file with some scripts. These will help you build and deploy your code.
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 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.
Hello World example doesn’t need much 👇
With that you’ve configured:
- an AWS Lambda function called
- 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.
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 👇
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 (
This function takes an
event, does whatever it wants, and returns a response with a
statusCode and a
body. 200 means
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 👇
PS: You should also follow me on twitter 👉 here.
It's where I go to shoot the shit about programming.