Kotlin as an option for service creation at Gympass
By: Rafael Pereira Santos
Tags: Microservices, Spring Boot, Gympass, Programming, Kotlin

Kotlin FAQs

Looking at Kotlin FAQs , we can find the following declaration: “ There are too many companies using Kotlin to list, but some more visible companies that have publicly declared usage of Kotlin, be this via blog posts, GitHub repositories or talks include , , or .”

After looking at the quantity of resources, there are a lot of other sources that indicate the same interest in Kotlin:

It seems that Kotlin is very well positioned in the majority of those rankings, and although sometimes it might be surpassed by languages like Go and Scala, it seems more consistent in those indexes.

Note, however, that Java is always near the top of every ranking, alongside Javascript. Kotlin isn’t Java, but a Java developer could easily adapt to a Kotlin environment as it has a direct interoperability model with Java.

Existing toolbelt to solve daily problems

Considering that we already have one technology stack up and running, we researched frameworks and libraries that could be adopted quickly within the stack to solve our daily routine problems during our services building. Below is a list with samples that we could find on this stack toolbelt to work on our daily routine. This list is dynamic, of course, and could change as our engineers begin to develop their components.

Kafka

Kafka official examples are all made in Java, so using Kotlin is no problem.

Swagger

There are plenty of ways to implement Swagger using Spring Boot, and this one this one is a good example

Datadog

There is already step-by-step documentation about how to implement datadog in a JVM based application.

Dynamo

Amazon has an official documentation for integrating Dynamo and Java.

Elasticsearch

Elasticsearch has a dedicated page for supported clients.

for supported clients. There is a specific client for Kotlin: ES Kotlin, that allows the user to use their DSL to better use Elasticsearch.

Postgres/MySQL

There is a nice looking library called Exposed that seems to address a bunch of integrations.

that seems to address a bunch of integrations. We have the Spring Data JPA library, which allows us to create easy repositories with a minimum boilerplate. The only possible drawback is the fact that it works only in a blocking sense.

library, which allows us to create easy repositories with a minimum boilerplate. The only possible drawback is the fact that it works only in a blocking sense. For a reactive SQL client, we have access to Spring Data R2DBC, which allows us to query MySQL and Postgres databases in a reactive manner, integrating better with Webflux. It is a little more verbose than JPA, but in case of a full reactive flow, it can be of interest.

REST Client

Retrofit is a library created in Java that gracefully attends this need, you can see examples of this use in the Kotlin spike in link and resources. This library supports blocking calls by default and reactive calls via coroutines, callbacks or, by means of adapters, Spring Reactor abstractions. In using Retrofit, we use the OkHttp Http client underneath the hood.

Testing

JUnit Jupiter will be our test engine.

will be our test engine. JUnit 5 is a good option for a more traditional style of unit tests, running over the JUnit Jupiter engine.

is a good option for a more traditional style of unit tests, running over the JUnit Jupiter engine. For more complex integration tests, we can use the Spring Test Starter library, which works with JUnit 5 and automatizes to great lengths the process of configuring the environment, as can be seen in this tutorial .

. For those accustomed with Rspec and Spec, there too exists Spek, a BDD style test framework, running over the JUnit Jupiter engine.

Some other frequently asked questions that we faced during the request for comments fase

Why not Micronaut?

Micronaut showed great promise during our research, with gains of memory footprint and throughput. Our discussions showed that we could see potential gains, but using Micronaut would deprive us of using all the know-how on Spring Boot available on the internet and on the market.

Because of this, we chose to use Spring Boot as the framework, so we could choose a path that will allow us to move as fast as possible with a great degree of quality, in a way that will be welcoming to every new developer approaching the stack for the first time. And although it is not the most efficient route, we believe that the gains in developer productivity will outperform the gains in memory footprint and response time.

We might discuss this approach in the future, depending on the evolution of Kotlin inside Gympass, but the decision seems like the correct one for now.

Spring Webflux or Spring Web MVC? Blocking or not Blocking?

At first, it seems like Webflux is the obvious choice, a framework that seems to outperform Web MVC in every aspect, even when the Spring Web MVC vs Spring Webflux issue is raised.

Even so, analyzing the two worlds, it seems that not only there is a lot of overlap between the two libraries, but Webflux has some drawbacks too:

Venn Diagram — Spring MVC or WebFlux?

It seems that Spring MVC works best with libraries that are mandatorily blocking, like JPA, JDBC and others. Not only that, but a non reactive code is a code easier to understand and debug, as reactive code can be running on a thread pool with an infinitude of threads over an event loop. For both Reactor and coroutines, we have stack traces of diminishing investigative power, lowering the transparency of how the application is running and how errors happen. There is even the risk of some Spring functionalities not existing inside Spring Webflux but existing inside MVC, and the process of filter creation being harder inside the Webflux environment. It seems like Web MVC is a more beginner friendly library than Webflux.

Outside of that, some very important aspects to be in favor of using Webflux. By using Webflux we gain access to the creation of routes via a routing DSL that reminisces Akka routes model. And just by using not only Webflux, but libraries that do IO in a reactive manner, we gain APIs that scale better with more concurrent users, which can be game changing in projects that have a high degree of concurrent requests.

After listing those arguments of both web frameworks, it seems that the balance between the two is closer than at first sight. Even so, one would argue that Webflux by default seems to already offer throughput gains over Web MVC just by being used, outside of cases that use JDBC, as shown on our benchmarks. There is the fact that Webflux allows the user to use the @Controller syntax already popular with Web MVC, diminishing the gap between the two. We could even say that we can make the same blocking endpoint in both with minimal differences this way, and that sometimes it is a valid choice, as the complexity, debugging and error discovery of endpoints.

A request that is purely CPU bound? Imperative.

A request rarely called, with little or no IO and complex logic? Imperative with a beginners team, reactive with a more experienced team.

A request that is moderately called, with IO inside it and complex logic? Imperative with a beginners team, reactive with a more experienced team.

A request that is moderately called, with IO inside it and no complex logic? Reactive.

A request that is known to be a bottleneck, with any non zero quantity of IO inside it? Reactive.

It seems that the best choice is defaulting to Webflux and using the simplest way to solve the given task, as we must consider not only the performance, but how much it needs someone with a higher level of know how to understand what is happening and maintaining it:

This choice is not as clear cut as the case of use of Spring JDBC/JPA instead of R2DBC in cases of MySQL/Postgres access, because it shows that MVC outperforms Webflux in those cases.