# MVIKotlin: a state container for Kotlin Multiplatform that refuses to own your architecture

> MVIKotlin is a Kotlin Multiplatform framework that gives an application one source of truth for state, plus logging and time travel debugging, while leaving navigation, screens and the reactive library to you. This looks at what the library actually commits to, and what it deliberately leaves out.

**arkivanov/MVIKotlin** — Extendable MVI framework for Kotlin Multiplatform with powerful debugging tools (logging and time travel)

- Repository: https://github.com/arkivanov/MVIKotlin
- Website: https://arkivanov.github.io/MVIKotlin
- Stars: 1,034 · Forks: 43
- Language: Kotlin
- License: Apache-2.0
- Published: 2026-10-19 · Updated: 2026-10-19 · Language: en
- Canonical page: https://hysenlabs.com/projects/arkivanov-mvikotlin

## One source of truth for state, and nothing else

MVI stands for Model-View-Intent, and the pattern it implements is unidirectional data flow: data circulates between model and view in one direction only, from model to view and from view to model. The name suggests a full application architecture. The library documentation is careful to say it is not one.

MVIKotlin does not bring or enforce any particular architecture, and it states one primary responsibility: to provide a single source of truth for `State`. The scope of that state is deliberately undefined. It can be a whole app, a single screen, a feature, or part of a feature. There are two further optional responsibilities the library can take care of: an abstraction for UI with efficient updates through diffing, and lifecycle aware connections, called bindings, between inputs and outputs.

Everything else is out of scope. There are no definitions of screens, features or modules in the library, and no particular reactive framework is enforced or exposed. That last point is the one to sit with, because most state management libraries for Kotlin arrive with a worldview. This one arrives with a container and a direction of travel, and the consequences show up in how it is adopted: it can be introduced incrementally, starting in one small feature and expanding gradually, and you can experiment with different approaches to navigation, UI and modularization while keeping the state model consistent.

## The Store is the unit, not the screen

The core abstraction is the `Store`. The main module, `mvikotlin-main`, is described as the module with the default `Store` implementation, while `mvikotlin` itself holds the core interfaces and functionality. A store owns the state, accepts intents, and exposes outputs. What sits around it is yours to decide.

That decision is visible in the sample project, which is a todo list with a details view, implemented twice: once against the Reaktive library and once against coroutines. Each variant ships an Android application, an iOS Xcode project, and a web browser application over a shared module, with a shared database module underneath. The sample also demonstrates one possible architecture for a multiplatform project, in which each screen is represented by a controller class and the platform applications integrate those controllers and navigate between them.

Notice what the library does not do in that design. The screen is a controller class, which is the application's own type. Navigation is done by the platform application. The library is not providing a `Screen` type, a navigator, or a graph. That is the trade in the whole package: you get a consistent state model with a diffing and binding mechanism, and you keep full ownership of the structure around it.

## Adding the modules to a Gradle build

The library is published as a set of modules on Maven Central under the `com.arkivanov.mvikotlin` group, and the project recommends a minimum Gradle version of 5.3, with a pointer to the Kotlin documentation about metadata publishing mode to read first. A module is added to a module's `build.gradle` file with a single line:

```groovy
implementation "com.arkivanov.mvikotlin:<module-name>:<version>"
```

You pick the module name and version from the list of published modules. The set includes `mvikotlin` for core interfaces and functionality, `mvikotlin-main` for the default `Store` implementation, `mvikotlin-logging` for logging, `mvikotlin-timetravel` for the time travel feature, the extension sets `mvikotlin-extensions-reaktive` and `mvikotlin-extensions-coroutines`, and a small `rx` module with abstractions over rx and coroutines.

One entry in that list is struck through in the project documentation. The `keepers` module, which provided the `StateKeeper` and `InstanceKeeper` API for state preservation and object retention, is marked deprecated, with a link to the state preservation documentation as the replacement. That is an upgrade item to plan rather than a detail, because the API it carried was about keeping state across configuration changes and process death, which is exactly the kind of thing that is hard to remove later.

## Time travel is a debugging layer, not a runtime feature

The debug tooling is what separates this from a plain state container, and it is delivered as separate modules so it does not sit in your production path. `mvikotlin-logging` provides logging functionality with a customizable logger and formatter. `mvikotlin-timetravel` provides the time travel feature, and its target coverage is listed precisely: multiplatform for all supported targets, export and import of events for Android, an IntelliJ IDEA and Android Studio plugin for Android apps, a desktop client application for Android, Java and native Apple apps covering iOS, watchOS, tvOS and macOS, and a Chrome DevTools extension for web browser apps.

The tooling spread across three different hosts is the honest cost of a multiplatform debugging story. An Android developer works in the IDE plugin, a Java or native developer works in the desktop client, and a web developer works in the browser devtools. The library provides the event stream and the transport; the inspection surface is a separate application per host.

Targets covered by the framework itself are broad: Android, JVM, iOS, watchOS, tvOS, macOS, linuxX64, JavaScript, and Wasm, the last since `4.0.0-alpha02`. Wasm being the newest addition is worth noting, because it is the target most likely to still be settling.

## Reactive library optional, and Decompose sits in a different slot

The main functionality of the framework does not depend on any reactive library or coroutines library. Extensions for Reaktive and for coroutines are provided as separate modules, so the reactive choice is a decision you make at the dependency level, not a decision the framework forces. The sample project reinforces that by shipping the same todo application in both flavours, with the shared database and the state model unchanged between them.

The alternative worth naming is Decompose, which comes from the same author and appears in the documentation for a different reason. If you are using declarative UI frameworks such as Jetpack Compose, Multiplatform Compose by JetBrains, SwiftUI or React, the project suggests using Decompose for the architecture and notes that MVIKotlin plays nicely with it. The difference in approach is real rather than cosmetic: Decompose is suggested for architecture, while MVIKotlin is a single owner of state. They are complementary, and the point where they overlap is exactly the point where you have to decide which one owns a given concern.

Another alternative is not using a shared state container at all, and keeping platform-specific state handling per target. That works when the shared logic is small, and it fails as soon as the same business rules must behave identically on four platforms, which is the situation MVIKotlin was built for.

## Feature complete, and the release rhythm says so

The project documentation carries a note that is unusual to see in a README, and it is worth reading exactly as written: the project is not stale, it is feature complete, and the author is actively keeping it up to date with necessary maintenance and updates. That is a deliberate framing, and the release history backs up the second half of it while explaining the first. Version 4.4.0 was released on 2026-04-25, 4.3.0 on 2025-01-16, and 4.2.0 on 2024-08-08. The last push to the repository was on 2026-08-09.

So this is a project with a small, deliberate scope and a maintenance-only cadence, not a churn of features. If you are looking for a fast-moving framework that will keep adding capabilities, this is the wrong expectation. If you want a stable state model that will not break under you while you work, that is a fair trade, and the deprecation of `keepers` shows the author does make breaking changes when a better API appears.

The licence is Apache-2.0, with the `LICENSE` file at the repository root, and the code is published to Maven Central under the standard `com.arkivanov.mvikotlin` coordinates, so there is no unusual licensing question for a commercial application. The repository itself keeps a `detekt.yml`, a `deps.versions.toml`, a `mkdocs.yml` for the documentation site, and a `tools/` directory, and questions and ideas are directed to GitHub Discussions and the Kotlin Slack channel `#mvikotlin`.

## Conclusion

MVIKotlin fits a multiplatform team that wants a single source of truth for state shared across Android, iOS, JVM, JavaScript and Wasm targets, and that values being able to add the pattern to one feature before refactoring the whole app. It does not fit a team that wants a full application architecture handed to it, because the library defines no screens, features or modules. Before you commit, read the state preservation documentation and plan the move off the deprecated `keepers` module, and check whether your time travel tooling target is covered, since the desktop client and the browser extension cover different platforms.

## FAQ

### Does MVIKotlin require a reactive library or coroutines?

No. The main functionality of the framework does not depend on any reactive or coroutines library, and extensions for Reaktive and for coroutines are provided as separate modules. The sample project implements the same todo application both ways, with Android, iOS and web apps in each variant.

### How do I add MVIKotlin to a Gradle project?

Add the required modules to your module's build.gradle file with `implementation "com.arkivanov.mvikotlin:<module-name>:<version>"`, taking the module names and versions from the published list on Maven Central. The project recommends a minimum Gradle version of 5.3 and points to the Kotlin documentation about metadata publishing mode.

### What replaced the deprecated keepers module in MVIKotlin?

The `keepers` module, which provided the StateKeeper and InstanceKeeper API for state preservation and objects retaining, is marked deprecated in the project documentation, which links to a state preservation page for the current approach. If you depend on it, plan the migration before upgrading further.

### Which platforms can I use the MVIKotlin time travel feature on?

The time travel feature is multiplatform for all supported targets, with export and import of events for Android, an IntelliJ IDEA and Android Studio plugin for Android apps, a desktop client for Android, Java and native Apple apps, and a Chrome DevTools extension for web browser apps.

### Does MVIKotlin define screens, features, or navigation?

No. The library states that everything else is out of scope, with no definitions for screens, features or modules, and it enforces no particular architecture. It offers a single source of truth for state, an optional UI abstraction with diffing, and lifecycle aware bindings, leaving navigation and structure to the application.

## Sources

- [arkivanov/MVIKotlin on GitHub](https://github.com/arkivanov/MVIKotlin)
- [License: Apache-2.0](https://github.com/arkivanov/MVIKotlin/blob/master/LICENSE)
- [Project website](https://arkivanov.github.io/MVIKotlin)
- [README](https://github.com/arkivanov/MVIKotlin/blob/master/README.md)
- [Releases](https://github.com/arkivanov/MVIKotlin/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/arkivanov-mvikotlin
