2026-05-12
Apollo Kotlin 5 is a major release focused on:
@defer/@stream), fragment arguments, service capabilities, onError, nullability, field extensions, @oneOf, schema coordinates, ...In addition, Apollo Kotlin 5 stabilizes the new WebSocket engine, adds new KMP targets, a new HTTP cache strategy on top of OkHttp, new compiler plugin APIs, and more.
Previous DeprecationLevel.WARNING symbols are now DeprecationLevel.ERROR.
Previous DeprecationLevel.ERROR symbols are removed.
Apollo Kotlin 5 is an incremental release. Most of the APIs are compatible with Apollo Kotlin 4. The main breaking changes are in experimental Data Builders and Apollo Compiler Plugins.
For an upgrade walkthrough, see the v5 migration guide.
Apollo Kotlin 5 implements the latest version of the GraphQL specification draft as well as support for many experimental RFCs.
Those RFCs solve long-standing pain points in GraphQL, such as semantic nullability or fragment arguments.
incremental/v0.2 format for @defer and @stream (#6331).onError (#6860).@ignore support (#6900).@oneOf input objects when they create cycles (#6894).The Gradle plugin now uses Gratatouille classloader isolation, instead of GR8 relocation previously (#6524). This makes the plugin more robust and easier to debug.
Apollo Kotlin 5 uses KGP 2.3, with 2.1 compatibility for JVM and Android consumers. Native and JS consumers must compile with KGP 2.3+.
linuxX64 (#6493), linuxArm64 (#6929) and watchosDeviceArm64 (#6791) targets.com.android.kotlin.multiplatform.library (#6703, #6707, #6736).Accept header to introspection queries (#6616).Apollo Kotlin 5 stabilizes the new WebSocket API, making it easier to manage the lifecycle of the WebSocket and retry subscriptions.
com.apollographql.apollo.ws) is deprecated (#6774).RetryStrategy (#6764).ApolloRequest.Builder.url(String) (#6758).ApolloCall.extensions() (#6834).ApolloCall.ignoreUnknownKeys and ApolloClient.Builder.ignoreUnknownKeys (#6473).JsonReader state if a field throws in-flight (#6775).Optional.Absent a data object (#6686); use if/else to avoid Int boxing (#6688).The normalized cache artifacts are also deprecated and moved to a separate repository apollo-kotlin-normalized-cache (#6888).
This new cache supports:
Note that the SQLite storage format is not backward-compatible. See the dedicated migration guide for more details.
The legacy apollo-http-cache artifact is deprecated.
Instead, Apollo Kotlin now uses OkHttp's cacheUrlOverride() and supports POST caching via enablePostCaching (#6739).
See the migration guide for more details.
Service.pluginsArguments (#6523, #6622).Service.issueSeverity() to control the severity of compiler issues per type (#6731).Service.generateApolloEnums to generate enums as a sealed hierarchy with a __Known interface (#6611).generateApolloProjectIdeModel task (#6666).apollo-ast (#6868).DocumentTransform.transform after processing (#6510).@link Purpose and Import definitions (#6838).equals(), hashCode(), copy(), and toString() (#6843)./* and */ in KDocs (#6805).checkCapitalizedFields (#6502).IndexOutOfBoundsException in keyFields validation (#6748).checkCapitalizedFields (#6718).2026-05-04
Fix for a performance regression in the compiler (#6938). Many thanks @apramana for diving into this.
2026-04-27
First release candidate of Apollo Kotlin 5.
@catchByDefault in executable documents (#6932)2026-04-07
Compatibility release for Kotlin 2.4.0-Beta1
2026-04-07
Compatibility release for Kotlin 2.4.0-Beta1
2026-03-20
As the new features stream is drying up, this version is probably one of the last alpha before going -rc.
@ignore (https://github.com/apollographql/apollo-kotlin/pull/6900)org.gradle.category attribute and use reverse DNS naming to avoid name clashes (https://github.com/apollographql/apollo-kotlin/pull/6886)@oneOf input objects. (https://github.com/apollographql/apollo-kotlin/pull/6894)compileSdk version to 35 for better compatibility (https://github.com/apollographql/apollo-kotlin/pull/6899, https://github.com/apollographql/apollo-kotlin/pull/6902)Many thanks to @eboudrant for the contributions in this release 💙
Full Changelog: https://github.com/apollographql/apollo-kotlin/compare/v5.0.0-alpha.5...v5.0.0-alpha.6
2026-03-16
Maintenance release that adds a new KMP target and makes it easier to work with the new cache and AGP9.
This version also bumps KGP to 2.2. This is transparent for Android/JVM consumers but requires native/JS/wasm consumers to use KGP 2.2 to compile against 4.4.2.
This version is "golden-path ready". It supports latest GraphQL experimental features:
It also bumps KGP version to 2.3.10. This has no impact for JVM/Android consumers but requires Native/JS/Wasm consumers to compile with Kotlin 2.3.
onError (#6860)2025-01-30
./gradlew download${Service}ApolloSchemaFromIntrospection was crashing due to a bad class relocation (https://github.com/apollographql/apollo-kotlin/issues/6863)2026-01-23
Many thanks @MatthewFolbigg, @scana, and @simonlebras for their contributions to this release!
ApolloCall.extensions() in https://github.com/apollographql/apollo-kotlin/pull/6834Purpose and Import definitions in https://github.com/apollographql/apollo-kotlin/pull/6838Most of the development is now made in the 5.x alpha. This version backports compatibility with AGP9 as well as a few other fixes.
@catch support for responseBased codegen (#6698)ApolloInterceptor.InsertionPoint to control where the interceptors are added (#6767)2025-11-13
@stream supportYou may now use @stream to stream list responses from a compatible server.
To do this, opt in support for the incremental:v0.2 protocol:
val apolloClient = ApolloClient.Builder()
.networkTransport(
HttpNetworkTransport.Builder()
.serverUrl("http://example.com/graphql")
.incrementalDeliveryProtocol(IncrementalDeliveryProtocol.V0_2)
.build()
)
.build()
Using @defer and @stream will stay opt-in until the RFC is merged.
The experimental WebSockets are promoted to stable. In particular, the request url may now be changed in interceptors. This can be used together with RetryStrategy to change the authentication parameters when retrying a subscription. The previous implementation (using the com.apollographql.apollo.ws package name) is now deprecated.
Read more in the migration guide.
You can now use OkHttp cacheUrlOverride() to cache POST requests.
To do so, configure a cache on your OkHttpClient and use enablePostCaching:
val apolloClient = ApolloClient.Builder()
.networkTransport(
HttpNetworkTransport.Builder()
// Enable POST caching
.httpRequestComposer(DefaultHttpRequestComposer(serverUrl = mockServer.url(), enablePostCaching = true))
.httpEngine(
DefaultHttpEngine {
OkHttpClient.Builder()
.cache(directory = File(application.cacheDir, "http_cache"), maxSize = 10_000_000)
.build()
}
)
.build()
)
.build()
The existing apollo-http-cache artifacts have been deprecated. Moving forward, leveraging the cache of existing clients (OkHttp, Ktor, etc...) is the recommended way to do caching at the HTTP layer.
Read more in the migration guide.
The Gradle plugin now works with AGP 9 and the com.android.kotlin.multiplatform.library plugin.
Service.issueSeverity()You may now control the severity of issues found by the compiler in your Gradle scripts:
service("service") {
packageName.set("com.example")
// Do not fail the build on unused fragments
// Valid values are the names of the subclasses of `com.apollographql.apollo.ast.Issue`
issueSeverity("UnusedFragment", "warn")
}
@catch support for responseBased codegen by @martinbonnin in https://github.com/apollographql/apollo-kotlin/pull/6697Service.issueSeverity() by @martinbonnin in https://github.com/apollographql/apollo-kotlin/pull/6731@defer and @stream as of incremental/v0.2 by @BoD in https://github.com/apollographql/apollo-kotlin/pull/6331ApolloRequest.Builder.url(String) by @martinbonnin in https://github.com/apollographql/apollo-kotlin/pull/67582025-08-21
In this new alpha of v5, here are the main highlights:
generateApolloEnums option to generate enums as a sealed hierarchy distinguishing known and unknown valuesYour feedback is greatly appreciated as you try the new version!
To migrate your project, please read the migration guide (work in progress).
Service.generateApolloEnums to generate enums with a __Known interface (#6611)fetch (#6674)Many thanks to @pedromfmachado, @jvanderwee, @aryapreetam and @francescocervone for the contributions and help in this release 💜
2025-08-21
This is maintenance release that includes a few fixes.
Many thanks to @francescocervone for the Gradle plugin fix 💜
2025-07-25
Maintenance release to fix the Accept: header during introspection. Many thanks @pedromfmachado for diving into this!
This release also contains infrastructure work:
This is the first alpha release of version 5.0.0. Previous DeprecationLevel.WARNING are turned into DeprecationLevel.ERROR. Previous DeprecationLevel.ERROR are removed.
For details about how to migrate, read the migration guide draft. This migration guide is still work in progress. Feedbacks are welcome as you try the new version!
Infrastructure:
Gradle
Compiler:
Runtime:
ApolloCall.ignoreUnknownKeys and ApolloClient.Builder.ignoreUnknownKeys (#6473)AST:
Execution
2025-06-18
This is maintenance release that fixes an issue with Gradle task dependencies when using connectToAndroidSourceSet().
This release also introduces an Enhanced Client Awareness feature that adds the version of the library to
requests in the extensions object. This is useful for server-side analytics and debugging. This is enabled by default,
and can be disabled by calling sendEnhancedClientAwareness(false) on your ApolloClient.Builder.
Many thanks to @calvincestari for the client awareness contribution 💜
2025-06-05
Version 4.3.0 allows adding multiple compiler plugins and stabilizes ApolloCompilerPlugin.beforeCompilationStep() as the main entry point for compiler plugins. Read more in the compiler plugins documentation page.
This allows to move some cache-specific code generation logic to the new normalized cache repo and better separate concerns.
Moving forward, ApolloCompilerPlugin.beforeCompilationStep() and ApolloCompilerRegistry.registerOperationIdsGenerator() are considered stable because they play an important part in setting up persisted queries. Other APIs are considered more advanced and will most likely stay unstable for the foreseeable future.
Many thanks to @gnehz972 and @mengdd for their fixes about HTTP batching 💜
2025-04-28
@map and @mapTo (#6404)It is now possible to configure the adapters to use with scalars by using the @map directive:
extend schema @link(url: "https://specs.apollo.dev/kotlin_labs/v0.5/", import: ["@mapTo", "@map"])
extend scalar Date @map(to: "kotlinx.datetime.Instant", with: "com.apollographql.adapters.InstantAdapter")
If the to parameter is an inline value class, use the inlineProperty parameter to have the generated code box/unbox the value. In that case, with needs to point to an adapter of the underlying type:
extend scalar Timestamp @map(to: "com.example.Timestamp", with: "com.apollographql.apollo.api.LongAdapter", inlineProperty: "ts")
For the common cases where the scalar can be represented as a built-in Kotlin type (String, Boolean, Int, Long, Float, Double), you can use @mapTo and the compiler infers the adapter and generates an inline value class automatically:
extend scalar Length @mapTo(builtIn: Long)
Downloading or converting an SDL schema from introspection now includes scalar definitions. This is required for clients to get a full view of the schema.
@disableErrorPropagationApollo Kotlin now automatically adds @disableErrorPropagation if your server supports it and you opted in @catchByDefault in your schema extensions. This allows to use non-null types more liberally and still get support for partial data.
See https://github.com/graphql/graphql-js/pull/4348 and https://github.com/graphql-java/graphql-java/pull/3772
Many thanks to @bobbysothebys, @jvanderwee, @dhritzkiv, @lwasyl and @rohandhruva for all the contributions and help in this release 💜
@link' quickfix (#6402)HttpInterceptor.intercept() to throw Throwable (#6403)@DataBuilderDsl (#6484)withBuiltInDefinitions() and add flag to dump scalar definitions in SDL (#6389)@map and @mapTo (#6404)@ApolloInternal in public ABI (#6407)2025-01-24
The artifacts are now compiled with Kotlin 2.1.0. This change should be transparent for JVM and Android users thanks to languageVersion but requires klib consumers (native + JS) to update their KGP version to 2.1.0.
The IntelliJ plugin now has a dedicated mode for backend developers that uses Rover LSP (Language Server Protocol) to parse federation and connectors directives. This mode is only available when using IntelliJ Ultimate and other IDEs with LSP support. It is recommended for subgraphs authors.
This release supports Gradle isolated projects for shorter configuration times.
Many thanks to @jvanderwee, @varahash, @whyoleg, @StylianosGakis and @scana for all the contributions and help in this release 💙!
onSchema() once in multi-module scenrios (#6252)2024-11-04
Version 4.1.0 updates usages of Ktor from 2.3.11 to 3.0.0:
apollo-runtime-js or apollo-debug-server-jvm, you need to update your app to Ktor 3.0.0+ at the same time as updating to Apollo 4.1.0 (apollo-debug-server-android is unaffected).apollo-mockserver or apollo-ktor-support from this repo, you need to update to the new coordinates.All other cases are unaffected. In particular, apollo-runtime on Android and iOS uses OkHttp and NsUrlConnection respectively and is not impacted by the Ktor update.
You can read more details in the pull request.
application/graphql-response+jsonapplication/graphql-response+json is a new media type being introduced by the GraphQL over HTTP draft. It allows differentiating a valid GraphQL response from an error JSON response that could be transmitted by a cache or proxy in the HTTP chain.
If your server uses application/graphql-response+json and returns non-2xx response, Apollo Kotlin will now parse those responses and expose data and errors instead of returning an ApolloHttpException before.
If you need to access the status code, you can do so using executionContext[HttpInfo]. For an example, you can restore the throwing behaviour with the following interceptor:
object : ApolloInterceptor {
override fun <D : Operation.Data> intercept(
request: ApolloRequest<D>,
chain: ApolloInterceptorChain,
): Flow<ApolloResponse<D>> {
return chain.proceed(request).onEach {
val httpInfo = it.executionContext[HttpInfo]
if (httpInfo != null && httpInfo.statusCode !in 200..299) {
throw ApolloHttpException(httpInfo.statusCode, httpInfo.headers, null, "HTTP request failed")
}
}
}
}
The IntelliJ plugin is now compatible with K2 (#6150)
apollo-mockserver and apollo-ktor-support (#6215)2024-10-01
This release contains a handful of bug fixes and improvements.
ApolloInterceptor.InsertionPoint to control where the interceptors are added by @martinbonnin in https://github.com/apollographql/apollo-kotlin/pull/6761RetryStrategy by @martinbonnin in https://github.com/apollographql/apollo-kotlin/pull/6764Optional.Absent a data object by @JakeWharton in https://github.com/apollographql/apollo-kotlin/pull/6686if/else to avoid Int boxing by @JakeWharton in https://github.com/apollographql/apollo-kotlin/pull/6688@defer documentation by @calvincestari in https://github.com/apollographql/apollo-kotlin/pull/6751@ApolloExperimental symbols in public API (#6416)