Using Kotlin in a Serverless Architecture with AWS Lambda — Part 1: Setting Up the Project

Quick example of how to use Kotlin using Serverless Framework and AWS Lambda

Juan Urrego
Mar 13, 2018 · 8 min read
Image for post
Image for post

Welcome to the first in a series of articles about Using Kotlin in a Serverless Architecture with AWS Lambda. In these articles I will introduce a set of tools, concepts and code examples that will help you in the process of creating beautiful, serverless-based products.

Index

  1. Setting up your local development environment
  2. Designing and implementing a Multi-Tier Lambda App
  3. A Multi-layer core for your function: A request-dispatcher and micro HTTP router implementation
  4. Testing your code
  5. Integrating a RDBMS to your project (coming soon)
  6. Authentication & Authorisation using Amazon Cognito (coming soon)
  7. Creating an end-to-end RESTFul service (coming soon)

The Journey

For the frontend, we decided to go with a React project deployed on AWS S3. The FLUX Architecture, community, support, component based design and profesional experience with it, made React a perfect solution. Regarding S3, the service level agreemeent in terms of durabilty and availability, as well as a monthly price of $5 USD per month at most (for our particular case), made it a really good solution (we also use Cloudfront for improving caching and HTTPS support).

However, what about the backend? We needed an API-based solution ready to work with React, flexible enough for new requirements and, again, not too expensive. In the past, I’ve used AWS Lambda to develop highly scalable and available Microservices. Even with its limitations, I thought that it was a nice way to keep our architecture as serverless as possible. In previous projects, a combination of NodeJS + AWS Lambda was the solution, but I didn’t like the maintainability, debugging and performance of that too much. I’m not saying that it is bad, but I wanted something easier, faster and almost out of the box.

That’s how my journey of finding the best language and framework for this project started.

Every Millisecond Counts

During my research I found a really good article from Yan Cui called “Comparing AWS Lambda Performance When Using NodeJS, Java, C# or Python”. In this article the author makes four observations:

  • C# is the slowest language
  • Java is the fastest and most consistent one
  • Static languages have more consistent performance
  • Java packages are big

For me, it was amazing to see that Java was 6 times faster than C# and 3 times faster than NodeJS. Also, Java’s performance was really consistent, while Python and NodeJS had quite a random behaviour.

Update: Yun Zhi Lin created a new report based on Cui’s post. In this new article the results were a little bit different:

  • .Net Core 2.0 is now the one with the best performance
  • Go and Java have a similar performance
  • Compiled and dynamic languages have a consistent performance
  • Go packages are bigger than Java

Based on both articles, the final conclusions are:

  • .Net Core 2.0 is bringing a first class citizen performance to languages like C# and F#
  • Java still has a good performance
  • As Cui’s states about AWS Lambda: “Architects and engineers should have more confidence in choosing from all the available runtimes”

Kotlin vs Java

For a long time, I was quite excited about the idea of testing Kotlin in a real product, so I though that maybe this was the moment to do it. But why Kotlin over Java? There are several reasons but here it comes a couple of them:

  1. Kotlin provide a more concise, productive and safer alternative to Java
  2. Kotlin is interoperable with Java and runs with the same performance
  3. Kotlin is a functional and Object Oriented programming language
  4. Kotlin is becoming a trend. An example of that is Android, where people are starting to using Kotlin instead of Java.

In conclusion, it looks like Kotlin has more benefits over Java, than the other way around. So that’s when this trip started.

Serverless Framework

Then I found Serverless Framework, an agnostic and almost out of the box solution for AWS, Google Code, Microsoft Azure and IBM Open Whisk. Serverless came with templates for multiple languages, including Kotlin, and is becoming the de facto framework for any serverless project. AWS also has an alternative called SAM, however I loved the agnostic and plug-and-play concept from Serverless Framework.

So let’s stop talking and let’s begin with some code.

Creating the project

npm install -g serverless

Now let’s create our first project. I’m going to use the kotlin-jvm-gradle template, but if you want to use different one (maybe you prefer Maven) you can always choose a another option.

serverless create --template aws-kotlin-jvm-gradle --path your_service

By default, Serverless can also help you creating your AWS credentials file, you just need to execute this command:

serverless config credentials --provider aws --key EXAMPLE --secret EXAMPLEKEY

After using those commands, you should have a default folder structure like this:

Image for post
Image for post
Default folder structure using the kotlin-jvm-gradle template

To test that everything is working, from your project’s root directory, run the next command (then go to your AWS Account and use the UI console to test!):

./gradlew deploy

Note: According to Serverless documentation you can use the command serverless deploy -v. However, with Java-based-projects that’s not true because it needs to create a Fatjar with all the needed requirements (so the command will fail). By default, Serverless will set shadow as a dependency in the gradle file for those purposes. The deploy command will generate a build file called <project_name>-all.jar that is the one that’s going to be uploaded to the AWS Lambda function.

Setting up the project

Service: Name of the project itself. For Serverless framework it can be considered as a container of functions. In later articles, I will explain some SOA concepts that will help us to define the correct granularity of our functions.

service: your-service

Provider: The cloud provider that we are going to use and the runtime environment. In this particular case we are going to use AWS and Java8

provider:
name:
aws
runtime: java8

There is a couple of commented values that you may want to uncomment, like environment, stage, region and memory size. This last one is really important, because with Java a small memory size could generate erratic/non-consistent behaviour. My advise is to have at least 1GB of memory, so you can have something like:

provider:
name: aws
runtime: java8

# You can overwrite defaults here
stage: dev # Use dev, stag, prod, etc
region: eu-west-1 # Your preference region, in my case Ireland
memorySize: 1472 # It has worked for me

The last two properties that serverless also provides are environment (where you can define lambda environment variables) and IAM Role Statements. The first property is good if you’re not going to persist critical data. In case of credentials management, it is always better to use a Parameter Store, a vault (like Terraform Vault) or IAM roles (using statements).

Package: It just defines the packaging information (name and build directory).

package:
artifact:
build/libs/your-project-dev-all.jar

Functions: This is the place where you’re going to define your functions and events that would trigger them. The minimum data required for your function is the name and handler file for it. By default you will see something like this:

functions:
hello:
handler:
com.serverless.Handler

A cool thing about serverless is that in this definition we can add our HTTP events, indicating that we want an API Gateway with that specific endpoint. Something like this:

functions:
hello:
handler:
com.serverless.Handler
events:
- http:
path:
hello
method: get

In the previous example, serverless will build an API Gateway with an endpoint /hello that will accept HTTP GET requests that call the main function in the Handler.kt file.

https://<lambda_id>.execute-api.<region>.amazonaws.com/<stage>/hello

Another nice feature is that we can define what other events from SNS, S3, Cloudwatch, Alexa, Stream and Cognito can trigger the function. In the next case, the function will be triggered every single 10 minutes or via an API Gateway request.

functions:
hello:
handler:
com.serverless.Handler
events:
- http:
path:
hello
method: get
- schedule: rate(10 minutes)

Resources: This section is one of the big helpers from Serverless, given that we can keep control over the infrastructure that supports our code. Do you need DynamoDB tables, S3 Buckets, or Cognito pools? Just put it here and that’s all. This feature give us the opportunity to have everything in the same place and to manage the whole life cycle of our app using this serverless.yml file. If at any moment you remove an element from here, serverless state will understand that you no longer need that resource and will delete it (so be careful with that).

The next example defines a DynamoDB for our Users with an email column and Hash key (as well other properties like the read and write capacity units).

resources:
Resources:
UsersDynamoDbTable:
Type: 'AWS::DynamoDB::Table'
DeletionPolicy:
Retain
Properties:
AttributeDefinitions:
-
AttributeName: email
AttributeType: S
KeySchema:
-
AttributeName: email
KeyType: HASH
ProvisionedThroughput:
ReadCapacityUnits:
1
WriteCapacityUnits: 1
TableName: Users

Note: If you want to know more about the serverless.yml file, please go to their website.

Final Thoughts

Part 2: Setting up your local development environment

Tech@Travelstart

The technical side to building the largest Online Travel…

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store