Why We Write Micro-Services in Kotlin

Spruce is a title agency. Our platform enables fast, frictionless, and transparent real estate transactions across the country. We believe the future of real estate will be driven by automation and empowering homeowners, so our mission is to make real estate transactions amazing for everyone involved in the process.

When you buy or refinance a house, we’re the ones doing the paperwork and moving the money. If you’ve dealt with a title agency before, you may have found the experience surprisingly expensive and rather confounding. We’re working to change all that with software (and hiring engineers to build it).

We bootstrapped with Rails, but the nature of the domain — the insides of a title agency are a cross between a law firm and a bank — lent itself nicely to microservices, so we went shopping for the next platform. The strong preference was for the JVM — unrivaled at runtime maturity and the size and quality of the library ecosphere — but for the fact that its language options have always left a lot to be desired.

To consider just the most widely used ones, Java 11 with Spring Boot is a far cry from the much-maligned Java 5 with J2EE, yet the language is coming up on a quarter century and looks it. Scala is huge and demanding — anything non-trivial requires facility with monads, type-level concepts and Scala’s type inference limitations hobbling both. It’s also famously slow to code in. And Clojure is, of course, a LISP. Solid arguments have been made that its efficiencies pay for the learning curve (and there are fans on the team), but in the end writing code to generate legal paperwork and keep escrow accounts in a language without a static type checker was not considered a viable option. Enter Kotlin.

Designed by JetBrains to replace Java as the language of the IDEA platform, it’s solidly up-to-date without being unduly experimental, flawlessly interoperates with Java, and has excellent IDE support (which, given its provenance, you would expect). Its block syntax allows type-safe DSLs (domain-specific languages), and the early availability of an Android UI DSL has led to Kotlin becoming the de facto standard for new Android development. Yet it’s not limited to mobile — it can go anywhere Java can go, and several companies have been pioneering its use for back-end development. For almost two years now, Spruce has been a highly satisfied early adopter.

Kotlin checks off a solid set of basic features one expects from a statically typed language in 2019:

  • lambdas
  • proper higher-kinded types with type inference
  • preferred immutability
  • inline constructor syntax
  • null-safety
  • a solid if uninspired pattern matching with exhaustiveness checks
  • ADTs (algebraic data types), and
  • a suitable runtime library incorporating all of the above

It’s also self-consciously un-pure functional — there are, by design, neither monadic comprehensions nor type classes. But there are several excellent bonus features:

Here’s a utility extension function we frequently use to parse JSON with Jackson, also demonstrating the use of block syntax and reified types:

val mapper = ObjectMapper().apply {
   registerModule(KotlinModule())
}
inline fun <reified E> String.fromJson(): E =
   mapper.readValue<E>(this, object : TypeReference<E>() {})

And its usage:

val anObject: Map<String, Any> = “””{“what”: “that”}”””.fromJson()

Note that if the compiler can infer the type of the resulting value, you don’t need to specify the type argument to the function. The triple quotes are Kotlin’s raw string notation.

Kotlin's few gotchas so far included:

  • the potential to confuse receiver arguments in nested blocks/lambdas (alleviated by the use of the somewhat wordy this@ syntax)
  • the occassional type inference blip requiring an explicit cast
  • comparative, if tolerable, instability of the APIs. E.g. the upgrade from 1.2 to 1.3 changed the implementation details of reflection, quietly breaking JSON parsing with confusing error messages about missing classes

If your team should like to adopt Kotlin, having a team member with Java expertise will significantly smooth the ride.

We write our Kotlin micro-services using the excellent “server-as-a-function” framework http4k, to which we also contribute, publish them in Docker containers and deploy on Google Kubernetes Engine in an Istio service mesh. If any of this, or fixing the US home buying process, sounds like something you might want to be a part of, then as mentioned before, we are hiring.

Author image

About Alex Zuzin