// Copyright (C) 2024 Gradle, Inc.
//
// Licensed under the Creative Commons Attribution-Noncommercial-ShareAlike 4.0 International License.;
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

:gradle-issues: https://github.com/gradle/gradle/issues/

[[config_cache:usage]]
= Enabling and Configuring the Configuration Cache

[[config_cache:usage:enable]]
== Enabling the Configuration Cache

By default, Gradle does not use the Configuration Cache.

To enable it at build time, use the `configuration-cache` flag:

[source,bash]
----
$ ./gradlew --configuration-cache
----

To enable the cache persistently, set the `org.gradle.configuration-cache` property in `gradle.properties`:

[source,properties]
----
org.gradle.configuration-cache=true
----

If enabled in `gradle.properties`, you can override it and disable the cache at build time using the `no-configuration-cache` flag:

[source,bash]
----
$ ./gradlew --no-configuration-cache
----

[[config_cache:usage:ignore_problems]]
=== Ignoring Configuration Cache Problems

By default, Gradle fails the build if Configuration Cache problems occur.
You _can_ turn problems into warnings by enabling _warning mode_, but this is generally not recommended — see the warning below for the supported alternative.
The flag exists primarily for short-lived troubleshooting, for example to surface execution-time problems without fixing the entire configuration phase first.

To change this behavior at build time, use the following flag:

[source,bash]
----
$ ./gradlew --configuration-cache-problems=warn
----

NOTE: This does not guarantee that the build will succeed.

Alternatively, configure it in `gradle.properties`:

[source,properties]
.gradle.properties
----
org.gradle.configuration-cache.problems=warn
----

[WARNING]
====
Warning mode is a migration and troubleshooting aid and not intended as a persistent way of ignoring incompatibilities.
It will also not prevent new incompatibilities being accidentally added to your build later.

With warning mode enabled, Gradle stores cache entries even when problems are present.
On a cache hit, tasks run against deserialized state that may be incomplete or incorrect, which can produce silently wrong results or confusing errors — such as missing dependency information or empty inputs.

Instead, we recommend explicitly marking problematic tasks as <<configuration_cache_debugging.adoc#config_cache:task_opt_out,incompatible>> and keeping the default `problems=fail`.
====

[[config_cache:usage:max_problems]]
=== Allowing a Maximum Number of Problems

By default, Gradle fails the build once more than `512` Configuration Cache problems have accumulated.
This limit applies regardless of the `problems` mode, but in practice it is only reached under `problems=warn`, since `problems=fail` stops at the first problem.

You can adjust this limit by specifying the maximum number of allowed problems on the command line:

[source,bash]
----
$ ./gradlew -Dorg.gradle.configuration-cache.max-problems=5
----

Or configure it in a `gradle.properties` file:

[source,properties]
----
org.gradle.configuration-cache.max-problems=5
----

[[config_cache:usage:parallel]]
=== Enabling Parallel Configuration Caching

By default, Configuration Cache storing and loading are sequential.
Enabling parallel storing and loading can improve performance, but not all builds are compatible with it.

To enable parallel configuration caching at build time, use:

[source,bash]
----
$ ./gradlew -Dorg.gradle.configuration-cache.parallel=true
----

Or persistently in a `gradle.properties` file:

[source,properties]
----
org.gradle.configuration-cache.parallel=true
----

[WARNING]
====
The parallel configuration caching feature is _incubating_, and some builds may not work correctly.
A common symptom of incompatibility is `ConcurrentModificationException` errors during the <<build_lifecycle_intermediate.adoc#sec:configuration,configuration phase>>.
However, this feature is expected to work well for <<configuration_on_demand.adoc#sec:decoupled_projects,decoupled>> multi-project builds.
====

[[config_cache:usage:read_only]]
=== Making the Configuration Cache Read-Only

In some builds, such as CI builds running in ephemeral environments, it may be desirable for Gradle to use the Configuration Cache only when there's a cache hit.
If there's a miss, caching offers no benefit since the disk state won't be preserved across builds.

To enable read-only configuration caching at build time, use:

[source,bash]
----
$ ./gradlew -Dorg.gradle.configuration-cache.read-only=true
----

Or set it persistently in `gradle.properties`:

[source,properties]
----
org.gradle.configuration-cache.read-only=true
----

Note that if you enable this persistently, you'll need to explicitly disable it via the command line in order for Gradle to ever write to the configuration cache.

[WARNING]
====
The read-only configuration caching feature is _incubating_.
====

[NOTE]
====
Read-only mode is intended for environments where the cache directory is not preserved across builds.
It is *not* a mechanism for catching Configuration Cache problems in build logic.
On a cache miss, read-only mode skips serialization entirely so the build runs as fast as possible, which means any execution-time Configuration Cache violations in your build logic will not be detected.
Use the default mode if your goal is to verify that your build is Configuration Cache compatible.
====

[[config_cache:stable]]
== Enabling Strict Configuration Cache Mode

To help teams adopt configuration caching, Gradle provides a strict mode behind a dedicated feature flag.

You can enable this feature flag in your build using the following configuration:

====
include::sample[dir="snippets/optimizing-builds/configuration-cache/stableFeatureFlag/kotlin",files="settings.gradle.kts[]"]
include::sample[dir="snippets/optimizing-builds/configuration-cache/stableFeatureFlag/groovy",files="settings.gradle[]"]
====

Enabling the `STABLE_CONFIGURATION_CACHE` feature flag activates stricter validation and introduces the following behavior:

NOTE: Even when the Configuration Cache is not enabled, Gradle will warn if you <<configuration_cache_requirements.adoc#config_cache:requirements:build_listeners, register build listeners>>.

We recommend enabling this flag early to detect and resolve potential issues before the stricter behavior becomes the default in a future release.

[[config_cache:usage:invalidate]]
== Invalidating the Configuration Cache

The Configuration Cache is automatically invalidated when inputs to the configuration phase change.
However, some inputs are not yet tracked, meaning you may need to manually invalidate the cache when untracked inputs change.
This is more likely if you have <<configuration_cache_enabling.adoc#config_cache:usage:ignore_problems,ignored problems>>.

See the <<configuration_cache_requirements.adoc#config_cache:requirements>> and <<configuration_cache_status.adoc#config_cache:not_yet_implemented>> sections for more details.

The Configuration Cache state is stored in a `.gradle/configuration-cache` directory in the root of your Gradle build.

To manually invalidate the cache, delete this directory:

[source,bash]
----
$ rm -rf .gradle/configuration-cache
----

Gradle periodically checks (at most every 24 hours) whether cached entries are still in use.
Entries that have not been used for 7 days are automatically deleted.

[[config_cache:usage:input_opt_outs]]
== Temporary Opt-Outs for Configuration Cache Behavior

Gradle releases continuously tighten the Configuration Cache in two directions: detecting more cases where configuration logic interacts with the environment (so a value change correctly invalidates the cache) and expanding what must be serializable to survive across a cache hit.
Both changes increase correctness, but both can also introduce stricter rules that plugins and build logic must follow for optimal caching.

For adoption phases where a specific input tracker or serialization rule causes cache misses or errors in build logic you cannot immediately fix, Gradle provides opt-out properties that temporarily revert to earlier behavior.
The steps to follow:

* Identify the problem using the <<configuration_cache_debugging.adoc#config_cache:troubleshooting, Configuration Cache report>>.
** Fix undeclared configuration inputs or non-serializable state accessed by project build logic.
** Report issues caused by third-party plugins to their maintainers and update plugins once they are fixed.
* Use opt-out options for specific cases to temporarily revert to earlier behavior, most commonly to mitigate performance issues caused by outdated plugins.

The remainder of this section is organized around the two categories: input-detection opt-outs first, then serialization-behavior opt-outs.

[[config_cache:usage:input_opt_outs:input_detection]]
=== Input-detection opt-outs

It is possible to _temporarily_ opt out of configuration input detection in the following cases:

1. Gradle now tracks file system interactions, including checks such as `File.exists()` or `File.isFile()`, as configuration inputs.
+
To prevent input tracking from invalidating the cache due to these file system checks, use the `org.gradle.configuration-cache.inputs.unsafe.ignore.file-system-checks` property in `gradle.properties`.
List the paths to be ignored, relative to the root project directory, separated by `;`.
Wildcards (`*` for segments, `pass:[**]` for multiple segments) are supported.
Paths prefixed with `~/` are relative to the user's home directory.
For example:
+
[source,text]
.gradle.properties
----
org.gradle.configuration-cache.inputs.unsafe.ignore.file-system-checks=\
    ~/.third-party-plugin/*.lock;\
    ../../externalOutputDirectory/**;\
    build/analytics.json
----
2. Prior to Gradle 8.4, some undeclared configuration inputs that were never used during configuration could still be read when the Configuration Cache serialized the task graph.
However, these changes did not invalidate the cache.
+
Starting in Gradle 8.4, these undeclared inputs are correctly tracked and now cause cache invalidation.
+
To temporarily revert to the previous behavior, set the Gradle property `org.gradle.configuration-cache.inputs.unsafe.ignore.in-serialization` to `true`.

[[config_cache:usage:input_opt_outs:serialization_behavior]]
=== Serialization-behavior opt-outs

With the evolution of the Configuration Cache, Gradle may impose additional restrictions on build logic.
To make adoption smoother, it is possible to _temporarily_ opt out of these restrictions in specific cases:

1. Starting with Gradle 9.0.0, it is an error to use any provider, except a provider of `BuildService` returned from
link:{javadocPath}/org/gradle/api/services/BuildServiceRegistry.html#registerIfAbsent(java.lang.String,java.lang.Class,org.gradle.api.Action)[`BuildServiceRegistry.registerIfAbsent`]
or
link:{javadocPath}/org/gradle/api/services/BuildServiceRegistration.html#getService()[`BuildServiceRegistration.getService`]
as an argument for
link:{javadocPath}/org/gradle/build/event/BuildEventsListenerRegistry.html#onTaskCompletion(org.gradle.api.provider.Provider)[`BuildEventsListenerRegistry.onTaskCompletion`].
+
Prior to Gradle 9, unsupported providers were silently discarded and never received events during cache-hit builds.
+
To temporarily revert to the previous behavior, set the Gradle property:
+
[source,properties]
----
org.gradle.configuration-cache.unsafe.ignore.unsupported-build-events-listeners=true
----

2. Starting with Gradle 9.8.0, standard output and error listeners registered on a task's logging manager during configuration (for example via
link:{javadocPath}/org/gradle/api/logging/LoggingOutput.html#addStandardOutputListener(org.gradle.api.logging.StandardOutputListener)[`LoggingOutput.addStandardOutputListener`] or
link:{javadocPath}/org/gradle/api/logging/LoggingOutput.html#addStandardErrorListener(org.gradle.api.logging.StandardOutputListener)[`LoggingOutput.addStandardErrorListener`]) are stored in the Configuration Cache and re-registered on a cache hit, so a listener that cannot be serialized is now reported as a problem.
+
Prior to Gradle 9.8.0, these listeners were silently discarded and never received output during cache-hit builds.
+
To temporarily revert to the previous behavior, set the Gradle property:
+
[source,properties]
----
org.gradle.configuration-cache.unsafe.skip-task-logging-listeners-serialization=true
----

Use these opt-out options sparingly and only when they do not impact task execution results.
These options are intended as temporary workarounds and will be removed in future Gradle releases.

[[config_cache:reacting]]
== Detecting the Configuration Cache from Build Logic

Build logic or plugin implementations can detect whether the Configuration Cache is enabled for a given build and adjust behavior accordingly.

The link:{javadocPath}/org/gradle/api/configuration/BuildFeature.html#getActive--[active] status of the Configuration Cache is provided in the corresponding link:{javadocPath}/org/gradle/api/configuration/BuildFeatures.html#getConfigurationCache--[build feature].
You can access it by <<service_injection.adoc#service_injection, injecting>> the link:{javadocPath}/org/gradle/api/configuration/BuildFeatures.html[`BuildFeatures`] service into your code.

This information can be used to:

- Configure plugin features differently when the Configuration Cache is enabled.
- Disable an optional feature that is not yet compatible with the Configuration Cache.
- Provide additional guidance to users, such as informing them of temporary limitations or suggesting adjustments to their setup.

Use this sparingly.
The goal of adoption is uniform behavior, not a different code path depending on cache state.
