All Versions
Latest Version
Avg Release Cycle
13 days
Latest Release

Changelog History
Page 1

  • v3.7.1 Changes


    πŸš€ A patch release with a few fixes.

    πŸ‘·β€ All changes

    • πŸ— πŸ‘·Data Builders: make DefaultFakeResolver open and stateless (#4468)
    • Kotlin 1.7.21 (#4511)
    • Introduce HttpFetchPolicyContext (#4509)
    • πŸ›  Fix usedCoordinates on interfaces (#4506)

    Many thanks to @Holoceo, @juliagarrigos, @davidshepherd7 and @eduardb for the feedbacks πŸ’™

  • v3.7.0 Changes


    This version adds multiple new low level features. These new features expose a lot of API surface, and they will probably stay experimental until 4.0. Feedback is always very welcome.

    ✨️ [new & experimental] compiler hooks API (#4474, #4026)

    Compiler hooks allow you to tweak the generated models by exposing the underlying JavaPoet/KotlinPoet structures. You can use it for an example to:

    • βž• Add a 'null' default value to model arguments (source)
    • πŸ— Introduce a common interface for all models that implement __typename (source)
    • βž• Add a prefix to generated models (source)
    • Any other thing you can think of

    πŸ”Œ To do so, make sure to use the "external" version of the plugin:

    plugins {
      // Note: using the external plugin here to be able to reference KotlinPoet classes

    πŸ”Œ And then register your hook to the plugin:

    apollo {
      service("defaultnullvalues") {

    ✨️ [new & experimental] operationBasedWithInterfaces codegen (#4370)

    0️⃣ By default, Apollo Kotlin models fragments with synthetic nullable fields. If you have a lot of fragments, checking these fields requires using if statements. For an example, with a query like so:

      animal {
        ... on WarmBlooded {
        ... on Pet {
        ... on Cat {

    you can access data like so:

    if (animal.onWarmBlooded != null) {
      // Cannot smart cast because of
    if (animal.onPet != null) {
    if (animal.onCat != null) {

    ⚑️ Some of the combinations could be impossible. Maybe all the pets in your schema are warm blooded. Or maybe only cat is a warm blooded. To model this better and work around KT-8819, @chalermpong implemented a new codegen that adds a base sealed interface. Different implementations contain the same synthetic fragment fields as in the default codegen except that their nullability will be updated depending the branch:

    when (animal) {
      is WarmBloodedPetAnimal -> {
      is PetAnimal -> {
        // Some pet that is not warm blooded, e.g. a Turtle maybe?
      is OtherAnimal -> {
      // Note how there is no branch for Cat because it's a WarmBloodedPetAnimal
      // Also no branch for WarmBlooded animal because all pets in this (fictional) sample schema are WarmBlooded. This could be different in another schema

    To try it out, add this to your Gradle scripts:

    apollo {

    Many many thanks to @chalermpong for diving into this πŸ’™

    ✨️ [new & experimental] usedCoordinates auto detection (#4494)

    0️⃣ By default, Apollo Kotlin only generates the types that are used in your queries. This is important because some schemas are really big and generating all the types would waste a lot of CPU cycles. In multi-modules scenarios, the codegen only knows about types that are used locally in that module. If two sibling modules use the same type and that type is not used upstream, that could lead to errors like this:

    duplicate Type '$Foo' generated in modules: feature1, feature2
    Use 'alwaysGenerateTypesMatching' in a parent module to generate the type only once

    πŸ”§ This version introduces new options to detect the used types automatically. It does so by doing a first pass at the GraphQL queries to determine the used type. Upstream modules can use the results of that computation without creating a circular dependency. To set up auto detection of used coordinates, configure your schema module to get the used coordinates from the feature module using the apolloUsedCoordinates configuration:

    // schema/build.gradle.kts
    dependencies {
      // Get the used coordinates from your feature module
      // If you have several, add several dependencies
    apollo {
      service("my-api") {

    πŸ”§ And in each of your feature module, configure the apolloSchema dependency:

    // feature/build.gradle.kts
    dependencies {
      // Depend on the codegen from the schema
      // But also from the schema so as not to create a circular dependency
    apollo {
      // The service names must match
      service("my-api") {

    πŸ‘·β€ All changes

    • βž• Add usedCoordinates configuration and use it to automatically compute the used coordinates (#4494)
    • Compiler hooks (#4474)
    • πŸ‘• 🐘 Use registerJavaGeneratingTask, fixes lint trying to scan generated sources (#4486)
    • βœ… Rename generateModelBuilder to generateModelBuilders and add test (#4476)
    • πŸ— Data builders: only generate used fields (#4472)
    • Only generate used types when generateSchema is true (#4471)
    • πŸ—„ Suppress deprecation warnings, and opt-in in generated code (#4470)
    • Multi-module: fail if inconsistent generateDataBuilders parameters (#4462)
    • βž• Add a decapitalizeFields option (#4454)
    • Pass protocols to WebSocket constructor in JSWebSocketEngine (#4445)
    • πŸ›  SQLNormalized cache: implement selectAll, fixes calling dump() (#4437)
    • Java codegen: Nullability annotations on generics (#4419)
    • Java codegen: nullability annotations (#4415)
    • OperationBasedWithInterfaces (#4370)
    • βœ… Connect test sourceSet only when testBuilders are enabled (#4412)
    • πŸ‘ Java codegen: add support for Optional or nullable fields (#4411)
    • βž• Add generatePrimitiveTypes option to Java codegen (#4407)
    • βž• Add classesForEnumsMatching codegen option to generate enums as Java enums (#4404)
    • πŸ›  Fix data builders + multi module (#4402)
    • πŸ”Œ Relocate the plugin without obfuscating it (#4376)
  • v3.6.2 Changes


    A patch version to fix compatibility with Kotlin 1.7.20 and another fix when calling ApolloStore.dump() with the SQL normalized cache.

    πŸ‘·β€ All changes

    • βž• Add support for KGP 1.7.20 (#4439)
    • πŸ›  Fix SQLNormalizedCache.dump() (#4437)
  • v3.6.1 Changes


    πŸ— A patch version to fix an issue with data builder and multi modules. Many thanks to @agrosner and @eduardb for catching this.

    πŸ‘·β€ All changes

    • πŸ›  Fix data builders in multi-modules scenarios (#4402)
  • v3.6.0 Changes


    πŸ— This version brings initial support for @defer as well as data builders.

    πŸ’™οΈ External contributors

    Many thanks to @engdorm, @Goooler, @pt2121 and @StylianosGakis for their contributions!

    ✨️ [new] Kotlin 1.7 (#4314)

    πŸš€ Starting with this release, Apollo Kotlin is built with Kotlin 1.7.10. This doesn't impact Android and JVM projects (the minimum supported version of Kotlin continues to be 1.5) but if you are on a project using Native or JS, you will need to update the Kotlin version to 1.7.0+.

    πŸ‘ ✨️ [new] @defer support

    πŸ›° @defer support is experimental in the Kotlin Client and currently a Stage 2 GraphQL specification draft to allow incremental delivery of response payloads.

    🚀 @defer allows you to specify a fragment as deferrable, meaning it can be omitted in the initial response and delivered as a subsequent payload. This improves latency for all fields that are not in that fragment. You can read more about @defer in the RFC and contribute/ask question in the @defer working group.

    πŸ›° Apollo Kotlin supports @defer by default and will deliver the successive payloads as Flow items. Given the below query:

    query GetComputer {
      computer {
        ...ComputerFields @defer
    fragment ComputerFields on Computer {
      screen {

    πŸ›° And the following server payloads:

    πŸ›° payload 1:

      "data": {
        "computer": {
          "__typename": "Computer",
          "id": "Computer1"
      "hasNext": true

    πŸ›° payload 2:

      "incremental": [
          "data": {
            "cpu": "386",
            "year": 1993,
            "screen": {
              "resolution": "640x480"
          "path": [
      "hasNext": true

    πŸ›° You can listen to payloads by using toFlow():

    apolloClient.query(query).toFlow().collectIndexed { index, response ->
      // This will be called twice
      if (index == 0) {
        // First time without the fragment
      } else if (index == 1) {
        // Second time with the fragment

    πŸ“š You can read more about it in the documentation.

    As always, feedback is very welcome. Let us know what you think of the feature by either opening an issue on our GitHub repo , joining the community or stopping by our channel in the KotlinLang Slack(get your invite here).

    πŸ— ✨️ [new] Data Builders (#4321)

    πŸ— Apollo Kotlin 3.0 introduced test builders. While they are working, they have several limitations. The main one was that being response based, they could generate a lot of code. Also, they required passing custom scalars using their Json encoding, which is cumbersome.

    πŸ— The data builders are a simpler version of the test builders that generate builders based on schema types. This means most of the generated code is shared between all your implementations except for a top level Data {} function in each of your operation:

    // Replace
    val data = GetHeroQuery.Data {
      hero = humanHero {
        name = "Luke"
    // With
    val data = GetHeroQuery.Data {
      hero = buildHuman {
        name = "Luke"

    πŸ‘·β€ All changes

    • πŸ›  fix registering Java scalars. Many thanks @parker for catching this. (#4375)
    • πŸ— Data builders (#4359, #4338, #4331, #4330, #4328, #4323, #4321)
    • βž• Add a flag to disable fieldsCanMerge validation on disjoint types (#4342)
    • πŸ›° Re-introduce @defer and use new payload format (#4351)
    • πŸ“‡ Multiplatform: add enableCompatibilityMetadataVariant flag (#4329)
    • βœ‚ Remove an unnecessary file.source().buffer() (#4326)
    • 0️⃣ Always use String for defaultValue in introspection Json (#4315)
    • ⚑️ Update Kotlin dependency to 1.7.10 (#4314)
    • βœ‚ Remove schema and AST from the IR (#4303)
  • v3.5.0 Changes


    πŸš€ With this release, Apollo Kotlin now uses Kotlin Native's new memory model. It also contains a number of other improvements and bug fixes.

    πŸ’™οΈ External contributors

    Many thanks to @glureau for carefully adding new watch targets βŒšπŸ’™.

    ✨️ [new] Kotlin Native: new memory manager (#4287)

    🐎 Apollo Kotlin is now requiring applications to use the new memory manager, a.k.a. new memory model. Thanks to this change, the restriction that operations had to be executed from the main thread on Apple targets is now removed. You can also use kotlinx.coroutines.test.runTest. Last but not least, benchmarks seem to indicate that performance is better under the new memory manager!

    ✨️ [new] @targetName directive (#4243)

    πŸ”§ This directive was introduced in v3.3.1 to allow overriding the name of enum values in the generated code. It has now been extended to allow configuring the generated name of Interfaces, Enums, Unions, Scalars and Input objects. This can be used to make the generated code nicer to use, or to avoid name clashes with Kotlin types (e.g. Long) in Kotlin Native.

    πŸ”Œ ✨️ [new] Automatic resolution of Apollo artifacts versions from the plugin version (#4279)

    ⬆️ From now on, you no longer need to specify explicitly the versions of Apollo dependencies: if omitted, the same version as the Apollo Gradle plugin will be used. This should facilitate upgrades and avoid potential mistakes:

    plugins {
      plugins {
      dependencies {
        // Replace this
        // implementation("com.apollographql.apollo3:apollo-runtime:3.5.0")
        // with

    βœ… 🚧 [deprecated] runTest (#4292)

    βœ… With the new memory model, Apollo's specific runTest method from apollo-testing-support is no longer useful and has been deprecated. If you were using it, you should now be able to use Kotlin's runTest instead, or simply runBlocking.

    🚧 [breaking] Automatic detection of type enum values.

    🚚 If you have an enum with a type value, this value used to name clash with the generated type property. This version now detects this case automatically and escapes type to type_. If you had previously used @targetName to workaround this issue, you can now remove it to avoid it being escaped twice:

  • v3.4.0 Changes


    πŸš€ This release contains a few important bug fixes (#4214, #4224, #4247, #4256), makes it possible to compile with Gradle πŸ”Œ 7.4 and apollo-gradle-plugin (#4218).

    It also introduces -incubating cache artifacts.

    πŸ’™οΈ External contributors

    Many thanks to @ArjanSM, @zebehringer, @mm-kk-experiments, @mune0903, @stengvac, @elenigen, @shamsidinb, @StylianosGakis for the awesome contributions πŸ˜ƒ!

    ✨️ [new] -incubating cache artifacts.

    This version introduces the below artifacts:

    • apollo-normalized-cache-incubating
    • apollo-normalized-cache-api-incubating
    • apollo-normalized-cache-sqlite-incubating

    These artifacts introduce new APIs to work with cache expiration and pagination (as well as other cache improvements in the future).

    🐎 These artifacts have no backward compatibility guarantees and most likely have worse performance than the non-incubating πŸ“š artifacts. Documentation will be added once the API stabilize. In the short term, the best place to look for examples βœ… are the integration tests:

    Note: The experimental withDates: Boolean argument was introduced in 3.3.1 in the regular artifacts and is removed πŸš€ as part of this release. Use the -incubating artifacts to use it.

    πŸ‘·β€ All changes

    • βž• add TrimmableNormalizedCacheFactory (#4239)
    • 🚚 🚧 remove withDates (#4257)
    • πŸ—„οΈ Chunk parameters in large responses (#4256)
    • πŸ›  Fix for improper handling of JsonNumber in BufferedSinkJsonWriter (#4247)
    • Incubating modules for the next gen cache (#4241)
    • πŸ›  Pagination: fixes in FieldRecordMerger and MemoryCache (#4237)
    • πŸ‘‰ make it possible to reuse a File Upload (#4228)
    • πŸ“‡ Persist Record arguments/metadata with the SQL Json backend (#4211)
    • requestedDispatcher -> dispatcher (#4220)
    • πŸ›  Fix test errors were emitted outside the Flow (#4224)
    • πŸ”Œ Make it possible to compile with Kotlin 1.5 and apollo-gradle-plugin (#4218)
    • πŸ›  πŸ–οΈ Relax MapJsonReader endObject, fixes reading inline + named fragments with compat models (#4214)
    • Introduce RecordMerger (#4197)
    • βž• Add @typePolicy(embeddedFields: String! = "") (#4196)
  • v3.3.2 Changes


    πŸš€ This is a hot fix release that fixes a crash that could happen in the codegen when using responseBased codegen in a multimodule setup. It also includes a fix for incorrect generated code when using certain reserved names in enum values.

    πŸ‘·β€ All changes

    • ⚑️ Update to KotlinPoet 1.12.0, fixes generating enum values whose name clashes with other symbols (#4034)
    • ⚑️ Update to Ktor 2 (#4190)
    • πŸ›  Fix NPE in checkCapitalizedFields (#4201)
  • v3.3.1 Changes


    πŸš€ This release introduces @typePolicy on interface/enums, improvements on subscription error handling, and on Test πŸ— Builders. It also contains a number of other improvements and bug fixes!

    ✨️ [new] @typePolicy on interfaces and unions (#4131)

    πŸ“„ The @typePolicy directive can now be declared on interfaces and unions. Thank you @bubba for the contribution!

    πŸ”Œ WebSockets / Subscriptions error handling (#4147)

    πŸš€ An issue where websocketReopenWhen was not called in some cases was fixed. Also, this release introduces SubscriptionOperationException. A SubscriptionOperationException will be thrown instead of the more πŸ‘· generic ApolloNetworkError if a subscription fails due to a specific operation error.

    πŸ— πŸ“ Test Builders improvements and fixes

    • πŸ— A DslMarker was added to improve usage with nested builders (#4089)
    • πŸ— When calling a builder, but not assigning it to a field, an error is now thrown, preventing mistakes (#4122)
    • The error message displayed when __typename is missing was made clearer (#4146)
    • πŸ›  Fix: use rawValue instead of name for enums (#4121)

    ✨️ [new] ApolloClient implements Closable (#4142)

    ApolloClient now implements okio.Closable so you can πŸ‘‰ use use with it. Thanks @yogurtearl for this contribution!

    ✨️ [new] experimental @targetName directive on enum values (#4144)

    If an enum value name is clashing with a reserved name (e.g. type) you can now use this directive to instruct the codeGen to use the specified name for the value instead. This directive is experimental for now.

    πŸ‘ ✨️ [new] experimental support for renaming directives (#4174)

    As we add more client directives, the risk of nameclash with existing schema directives increases. If this happens, you can now import Apollo client directives using @link:

  • v3.3.0 Changes


    πŸš€ This is the first release with HMPP support. If you're using ⚑️ multiplatform, updating to Kotlin 1.6.21 is strongly encouraged.

    πŸš€ This release also brings WebSocket related improvements and other fixes!

    ✨️ [new] Hierarchical MultiPlatform Project (HMPP) (#4033)

    πŸš€ When using Apollo Kotlin on a multiplatform project, this release is compatible with πŸ“„ the hierarchical project structure, which makes it easier to πŸ›  share common code among several targets. Using HMPP in your project also fixes some issues when compiling Kotlin πŸ“‡ metadata. See and for more details.

    βœ‹ Note: If you're using multiplatform, we strongly encourage updating to Kotlin 1.6.21. If that is not an option, you might have issues resolving dependencies. More infos in this issue.

    ✨️ [new] WebSocketNetworkTransport.closeConnection (#4049)

    This new method can be used in conjunction πŸ— with reopenWhen to force a reconnection to the server. This could be useful for instance when needing to pass new auth tokens in the headers. If you were using subscriptionManager.reconnect() in 2.x, closeConnection is a simple way to achieve the same behaviour.

    πŸ›° ✨️ [new] GraphQLWsProtocol.connectionPayload is now a lambda (#4043)

    πŸ›° With GraphQLWsProtocol, if you need to pass parameters to the connection payload, previously you would pass them as a πŸ— static map to the builder. With this change you can now pass a lambda providing them as needed. This facilitates passing fresh auth tokens when connecting.

    ✨️ [new] Add insecure option to download schema (#4021)

    You can now use the --insecure flag when downloading a schema πŸ”§ with downloadApolloSchema πŸ”§ , to bypass the certificate check, which can be useful if a server is configured with a self-signed certificate for instance.

    πŸ‘·β€ All changes

    • βž• Add WebSocketNetworkTransport.closeConnection (#4049)
    • πŸ›° Made connectionPayload as suspend function in GraphQLWsProtocol (#4043)
    • ⚑ Ignore unknown websocket messages (#4066)
    • Kotlin 1.6.21 & HMPP (#4033)
    • Provide a Content-Length when using Upload (#4056)
    • ☁️ add HttpRequest.newBuilder(url, method) (#4038)
    • Escape enum constants (#4035)
    • πŸ›  Fix the Moshi adapter used for OperationOutput. Moshi cannot get the type parameters from the typealias automagically (#4022)
    • βž• Add insecure option to download schema (#4021)
    • Try to reduce allocations in MapJsonReader (#3935)
    • βœ… πŸ”’ Deprecate BearerTokenInterceptor and provide tests and docs instead (#4068)

    ❀️ External contributors

    πŸš€ Many thanks to @CureleaAndrei and @kdk96 for contributing to this release! πŸ™

    πŸ—„ βš™οΈ Deprecations

    • BearerTokenInterceptor was provided as an example but is too simple for most use cases, and has therefore been deprecated in this release. This page provides more details about authentication.
    • πŸ‘€ The previous ways of passing parameters to the connection payload with GraphQLWsProtocol has been deprecated (see above).