Taming the Unruly Code: Feature Flags in Kotlin Projects

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Preface: Why Do Features Break Releases?

Every developer has at least once found themselves in a situation where a shiny new feature is ready, but it cannot be released. Either it hasn't passed full QA, or marketing hasn't prepared the banners yet, or it's simply scary to press the "Deploy" button on a Friday evening. At that moment, we usually start writing if statements, switching BuildConfig, or, even worse, commenting out code.

Sound familiar? Welcome to the world of feature flags (or feature toggles). This is not just "another architectural thing." It's your lifeline that allows you to deploy code to production but enable it only for a select few. In this article, we'll break down how to implement feature flags in Kotlin projects — from simple solutions to advanced systems. And yes, there will be a lot of code.



What is a Feature Flag and Why Do You Need It?

A Feature Flag (also known as a feature toggle) is a software switch that allows you to enable or disable functionality without changing code or redeploying. Imagine being able to push a new recommendation algorithm to production but make it active only for 5% of users. Or enable it only for company employees for internal testing. Pretty cool, right?

Here are a few scenarios where feature flags are indispensable:

  • Canary releases: Roll out a new feature to 1% of servers, monitor errors, and gradually increase the percentage.
  • A/B testing: Test which UI version converts better without duplicating the entire project.
  • Kill switch: If a new feature starts consuming too much memory or causes a bug, you simply turn it off with one action (or an API request).
  • Separating release from deployment: The code is deployed, but the feature "sleeps" until date X.

In Kotlin, which is actively used both for backend (Ktor, Spring Boot) and mobile applications (Android), feature flags become especially relevant due to strict typing and code cleanliness requirements.



Architecture: How Not to Turn Flags into Spaghetti

The biggest mistake beginners make is scattering if (flag.isEnabled()) { ... } else { ... } throughout the project. This leads to a situation where, after a month, you can't tell which code branches are alive and which are dead. We need feature management, not chaotic switches.

Good architecture is built on the principle of dependency inversion. Your business code should not know where the flag's value comes from (a file, a database, or an external service). It simply asks: "Hey, FeatureFlagService, is the new_checkout feature enabled?"

Let's consider two approaches: a simple one (for small projects) and an advanced one (for microservices and Kubernetes).



1. Simple Approach: Configuration and Enum

If you need to get started quickly and you're not building a system with a million requests per second, you can get by with a simple enum class and a configuration file (e.g., application.conf for Ktor or application.yml for Spring).

Let's create an enum of all features:

enum class Feature(val key: String) {    NEW_PAYMENT_FLOW("feature.new-payment-flow"),    DARK_MODE("feature.dark-mode"),    SMART_SEARCH("feature.smart-search")}

Now, the service that reads the config:

class FeatureFlagService(private val config: Map<String, Boolean>) {

fun isEnabled(feature: Feature): Boolean { return config.getOrDefault(feature.key, false) }

// For A/B tests, you can add randomization fun isEnabledForUser(feature: Feature, userId: String): Boolean { if (!isEnabled(feature)) return false // Simplest hash for splitting into groups val group = userId.hashCode() % 100 return group < 50 // 50% of users

Blogs

Book Recommendations