Battle-tested template project for backend with Kotlin and Ktor

Yev Kanivets
xorum.io
Published in
5 min readJul 16, 2021

With Kotlin and Ktor technologies gaining more popularity among the community of backend developers, dozens of different sample applications and templates are created and published as open-source projects.

Ktor is an asynchronous framework for creating microservices, web applications, and more. It’s fun, free, and open source. So it doesn't force any particular architecture, set of libraries, or framework to be used, which means that you are free to choose what’s best for you and your project.

Today, I’m finally ready to share my personal Ktor template, polished by almost a year of use in production applications. This article gives a short overview of the template, its architecture, chosen tools, and libraries.

Tools

Since we are using Kotlin to develop Ktor applications, pretty much any IDE compatible with Java/Kotlin should work. But the default choice is IntelliJ IDEA, of course. Community edition (free) will work just fine.

Postman is a great choice for documenting, testing, and sharing your backend APIs. There are many similar tools. You can use cURL requests, for example. But always think about your API users first. What will be the most convenient for them, as they depend on you a lot.

Structure

Most of the Kotlin projects (including Ktor) are powered by Gradle, so they look quite similar. My template isn't different, with many Gradle-related files in the root and single src folder.

Other files are related to Heroku deployment, but more on this later.

Architecture

Ktor isn’t forcing you for any particular approach, so you are free to choose and implement the architecture that fits your needs best.

In our case, we implemented classical MVC (Model — View — Controller) architecture with a public API instead of View and dedicated Interactors, which encapsulate all business logic related to each endpoint.

Firebase Auth

Most applications require some authentication and authorization business logic, so my template includes one of the possible implementations out of the box — Firebase Auth.

It can be easily integrated with the Ktor backend, described in detail in this article. The configuration efforts are minimal:

  • Generate testToken (http://jwtbuilder.jamiekurtz.com/) and testUserId (https://www.uuidgenerator.net/), and set them in FirebaseAuth.kt. These variables are needed to simplify testing endpoints using Postman or similar tools.
  • Create a new Firebase project. Put firebase admin key file to resources and name it firebase-adminsdk.json.

Feel free to change the authentication implementation to what best fit your needs. Firebase Auth is here to provide a good enough default option and demonstrate how 3rd party authentication providers can be integrated.

Libraries

There are dozens of production-ready libraries created by the Ktor team and community, which should cover most of your needs. You can discover the big part of it using the official Ktor Project Generator.

My template includes the absolute minimum of dependencies, which are necessary to make it work:

  • Authentication: feature to be able to authenticate users.
  • Serialization: feature to encode/decode JSON and other data formats.
  • Logging: feature to enable logging of network requests made by a server.
  • Exposed: ORM framework for Kotlin, which offers two levels of database access — typesafe SQL wrapping DSL and lightweight data access objects.
  • HikariCP: “zero-overhead” production-ready JDBC connection pool.
  • PostgreSQL: PostgreSQL JDBC Driver Postgresql to connect database with our Kotlin/Ktor application.
  • Sentry: straightforward way for crash reporting and analytics on backend.

Utilities

There are multiple utility classes in the util package. Let’s me describe them shortly, so you do not get confused when you see them in code:

  • ApplicationCall extensions declare some frequently used functions, which help you getting authenticated user’s id in calls and respond with errors when they occur. Feel free to add your own extensions here.
  • CrashLogger is a simple wrapper for Sentry dependency, so you can easily replace it with another service in the future if needed.
  • CrashLoggerFactory is responsible for initializing the crash reporting tool of choice. Here, it passes the environment variable to the Sentry initializer.
  • DatabaseFactory connects the Ktor application to the database using JDBC URL, which can be passed as an environment variable or hardcoded in the same file (for local testing). The dbQuery function must be used to execute database transactions on the background thread using coroutines.
  • HttpClientFactory solves the problem of creating HttpClient for calls from the Ktor backend to other 3rd party services. The request extension wraps the basic error handling and crash reporting.

Sample

The template wouldn't be complete without a sample code, so here is it — random Joke is taken from the official-joke-api.appspot.comin JokesRepostory by GetRandomJokeInteractor, and exposed to the outer world in the TestApi file.

Hosting

Ktor application is compiled to a jar file, which then can be run anywhere you want, from Raspberry Pi to the dedicated AWS instance. We’ve chosen Heroku for its simplicity, free plans, and transparent subscription-based pricing.

When you are ready to deploy to Heroku, set GitHub secrets that are used in github/workflows YAML files (GitHub Actions / CI): HEROKU_APP_NAME_PROD, HEROKU_APP_NAME_STAGING, HEROKU_EMAIL, and HEROKU_API_KEY.

Once you do it, any change merged or committed into dev will trigger a deployment to staging Heroku app, and main — to prod app. Also, you will probably want to update metadata in the app.json file.

Bottom line

Project templates can be a good starting point for your Ktor journey. There are dozens of templates for different use cases and developer needs. My template may be a good fit for those who need a simple yet complete starting project.

--

--

Yev Kanivets
xorum.io

Technical Lead Mobile @ 360Learning | KMP enthusiast | Husband & dad | Marathon finisher