---
title: "Medium Android App — Migrating from Apollo Kotlin 3 to 4: Lessons Learned"
description: "Migrating the Medium Android app from Apollo Kotlin 3 to 4 exposed cache and exception-handling issues that were hidden by the earlier implementation. Apollo Kotlin 4 uses a new group, plugin, and package identifier, places exceptions in ApolloResponse, and replaces ApolloCompositeException with a primary exception plus suppressed failures. CacheMissException errors appeared in watch() because programmatic cache IDs were incomplete or incorrect; the app addressed this with declarative type and field policies, __typename on every operation, cache-update helpers, and policy-aware safeWatch filtering. The migration also replaced executeV3(), removed fetchThrows = true, added a Currency scalar adapter, and identified HTTP batching and persisted queries as future improvements, while concluding that Apollo 4 produced a more robust cache integration after the underlying issues were fixed."
---

# Medium Android App — Migrating from Apollo Kotlin 3 to 4: Lessons Learned

[Medium](https://yomu.fyi/company/medium) · Pierrick CAEN · Oct 6, 2025

**Type:** Tutorial

## Summary

Migrating the Medium Android app from Apollo Kotlin 3 to 4 exposed cache and exception-handling issues that were hidden by the earlier implementation. Apollo Kotlin 4 uses a new group, plugin, and package identifier, places exceptions in ApolloResponse, and replaces ApolloCompositeException with a primary exception plus suppressed failures. CacheMissException errors appeared in watch() because programmatic cache IDs were incomplete or incorrect; the app addressed this with declarative type and field policies, \_\_typename on every operation, cache-update helpers, and policy-aware safeWatch filtering. The migration also replaced executeV3(), removed fetchThrows = true, added a Currency scalar adapter, and identified HTTP batching and persisted queries as future improvements, while concluding that Apollo 4 produced a more robust cache integration after the underlying issues were fixed.

## Context

The migration exposed CacheMissException errors throughout UI watchers because Apollo Kotlin 4 passes exceptions through ApolloResponse and the app’s programmatic cache ID configuration contained missing and incorrect key-generation logic. The app also needed to update exception handling for Apollo Kotlin 4’s changed response and composite-exception behavior.

## Approach / What changed

The app switched to declarative cache type and field policies, configured \_\_typename on all operations, added cache fragment read/write helpers, and implemented policy-aware safeWatch filtering that skips expected fallback exceptions. It also replaced executeV3(), removed fetchThrows = true, fixed ApolloCompositeException handling, and added a Currency scalar adapter.

## Takeaways

- Declarative type and field policies replaced programmatic cache IDs, making cache keys easier to match to types and fields.
- safeWatch filters CacheMissException or ApolloNetworkException according to the selected fetch policy, allowing later fallback responses to reach the UI while preserving meaningful failures.
- Apollo Kotlin 4 migration changes included the new com.apollographql.apollo identifier, ApolloResponse-based exception handling, execute() in place of executeV3(), and removal of fetchThrows = true.

**Tags:** [Android](https://yomu.fyi/topic/android), [Caching](https://yomu.fyi/topic/caching), [GraphQL](https://yomu.fyi/topic/graphql), [Kotlin](https://yomu.fyi/topic/kotlin)

- Source: [Medium](https://medium.engineering/medium-android-app-migrating-from-apollo-kotlin-3-to-4-lessons-learned-ff8d0d861cdb)
- Source URL: https://medium.engineering/medium-android-app-migrating-from-apollo-kotlin-3-to-4-lessons-learned-ff8d0d861cdb
- Ingested by Yomu: 2026-09-09T16:03:05.263Z

[Read original post](https://medium.engineering/medium-android-app-migrating-from-apollo-kotlin-3-to-4-lessons-learned-ff8d0d861cdb)
