PHPackages                             alleyinteractive/wp-soft-transients - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Caching](/categories/caching)
4. /
5. alleyinteractive/wp-soft-transients

ActiveLibrary[Caching](/categories/caching)

alleyinteractive/wp-soft-transients
===================================

Asynchronously update transients via WP Cron while serving stale data.

v1.0.1(1y ago)31.0kGPL-2.0-or-laterPHPPHP ^8.2

Since Feb 26Pushed 1y ago18 watchersCompare

[ Source](https://github.com/alleyinteractive/wp-soft-transients)[ Packagist](https://packagist.org/packages/alleyinteractive/wp-soft-transients)[ RSS](/packages/alleyinteractive-wp-soft-transients/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (2)Dependencies (5)Versions (5)Used By (0)

Soft Transients
===============

[](#soft-transients)

Asynchronously update transients via WordPress Cron while serving stale data.

This pattern provides a few advantages.

1. **Faster page loads**: If the transient is expired, the stale data is returned immediately and no "unlucky user(s)" have slower pageloads while data is refreshed.
2. **Reduced load on remote services**: If the transient is expired, the stale data is returned immediately and no request is made to the remote service until the cron task kicks off. This can be especially useful for high-traffic sites making remote requests, where many pageloads after an expiration could all attempt to update data at the same time. Instead, only one request is made to the remote service.
3. **No domino effect from unavailable services**: If a remote service is slow or unavailable, the site will continue to serve stale data until the service is available again. This can prevent a domino effect where one site becomes slow or unavailable because of a service disruption on another site.

Installation
------------

[](#installation)

Install the latest version with:

```
composer require alleyinteractive/wp-soft-transients
```

Usage
-----

[](#usage)

Soft Transients provides a wrapper for [WordPress's Transients API](https://developer.wordpress.org/apis/transients/), modifying its behavior such that the transient data may remain accessible after its expiration. Soft Transients stores the transient data alongside metadata, including the desired expiration time. After the expiration, stale data is returned and a cron task is enqueued. When that cron task executes, an application may then choose to take some action to refresh the expired data.

### Helper Functions

[](#helper-functions)

The library provides a class to interact with the transients, as well as a set of simplified drop-in replacement functions fully compatible with the WordPress Transients API. The helper functions are:

- `get_soft_transient( $transient_key )`: Retrieve the value of a transient.
- `set_soft_transient( $transient_key, $value, $expiration )`: Set the value of a transient.
- `delete_soft_transient( $transient_key )`: Delete a transient.

While the helper functions are convenient and easy to use, they do not provide the full functionality of the Soft Transients library. If you need to set custom cron hooks or pass custom arguments to the cron task, you should use the `Soft_Transient` class directly.

### Example

[](#example)

In this example, we're getting organizations from GitHub's API. We have a function to get the organizations from the API, and we have a function to get the organizations from the transient (`get_github_orgs()`).

In `get_github_orgs()`, if the transient is not available (e.g. this is the first time it's ever been called, or transients have been flushed), we'll get the organizations synchronously from the API and set the transient. We don't have to do this if we don't want, we could instead schedule the cron task to refresh the transient and return some "pending" signal to the caller.

If the transient is available, `get_github_orgs()` will return organization data indefinitely, even past the expiration time. If this function is called after the soft transient has expired, the Soft Transients library will schedule a cron task to run immediately (`transient_refresh_github_orgs`) which we then hook into to update the transient data.

```
use function Alley\WP\Soft_Transients\get_soft_transient;
use function Alley\WP\Soft_Transients\set_soft_transient;

function get_github_orgs_from_api() {
  $request = wp_remote_get( 'https://api.github.com/organizations' );
  if ( is_wp_error( $request ) ) {
    return $request;
  } elseif ( 200 !== wp_remote_retrieve_response_code( $request ) ) {
    return new WP_Error( 'bad_response', 'Bad response from GitHub API', $request );
  }
  $orgs = json_decode( wp_remote_retrieve_body( $request ), true );
  set_soft_transient( 'github_orgs', $orgs, HOUR_IN_SECONDS );
  return $orgs;
}

function get_github_orgs() {
  return get_soft_transient( 'github_orgs' ) ?: get_github_orgs_from_api();
}

function refresh_github_orgs_cron_task( $transient_key ) {
  $response = get_github_orgs_from_api();
  if ( is_wp_error( $response ) ) {
    // If the response is an error, schedule a new cron event. We can schedule this for whenever
    // makes sense for the given service, e.g. one minute from now.
    wp_schedule_single_event( time() + MINUTE_IN_SECONDS, current_action(), [ $transient_key ] );
  }
}
add_action( 'transient_refresh_github_orgs', 'refresh_github_orgs_cron_task' );
```

### Custom Cron Hooks and Arguments

[](#custom-cron-hooks-and-arguments)

This library allows you to set a custom cron hooks and/or pass custom arguments to the cron task. This can be useful if you're working with a variety of transient keys (e.g. a hash made up of some data like a url and arguments). In order to use this fuctionality, you can use the `Soft_Transient` class directly.

```
// Create the transient object.
$key       = 'my_request_' . md5( serialize( [ $url, $args ] ) );
$transient = ( new Soft_Transient( $key ) )
  ->set_cron_args( [ $url, $args ] )
  ->set_cron_hook( 'my_custom_cron_event' );

// Set a value.
$transient->set( get_remote_data( $url, $args ), HOUR_IN_SECONDS );

// Get a value.
$transient->get();

// Delete a value.
$transient->delete();

// Refresh a value.
add_action(
  'my_custom_cron_event',
  function( $transient_key, $url, $args ) use ( $transient ) {
    $transient = new Soft_Transient( $transient_key );
    $transient->set( get_remote_data( $url, $args ), HOUR_IN_SECONDS );
  },
  10,
  3
);
```

### Caveats

[](#caveats)

- When the transient has expired, the cron event is scheduled and the metadata is updated to indicate that the state is "loading". During the cron event, you should either successfully update the transient or schedule a new cron event to refresh the transient. If you do not, the transient will remain in the "loading" state. An hour after the expiration, if the soft transient is accessed, is still in the "loading" state, and the cron event is not scheduled, the library will then reschedule the cron event. It will continue to do so every time the soft transient is accessed and the cron event is not scheduled.
- As with WordPress's transients API, transients are not guaranteed; it is possible for the transient to not be available *before* the expiration time. Much like what is done with caching, your code should have a fall back method to re-generate the data if the transient is not available.

About
-----

[](#about)

WP Soft Transients is a derivative work of [Soft Transients by Matthew Boynes](https://github.com/mboynes/soft-transients) (c) 2014.

### License

[](#license)

[GPL-2.0-or-later](https://github.com/alleyinteractive/wp-soft-transients/blob/main/LICENSE)

### Maintainers

[](#maintainers)

[Alley Interactive](https://github.com/alleyinteractive)

###  Health Score

36

—

LowBetter than 82% of packages

Maintenance48

Moderate activity, may be stable

Popularity22

Limited adoption so far

Community13

Small or concentrated contributor base

Maturity53

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 63.6% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~57 days

Total

2

Last Release

388d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/d2679da8ee30c4d7eae16ffd2271484027b3b27be6d7fb8202d5e4c6d210881d?d=identicon)[alleyinteractive](/maintainers/alleyinteractive)

---

Top Contributors

[![mboynes](https://avatars.githubusercontent.com/u/465154?v=4)](https://github.com/mboynes "mboynes (7 commits)")[![mogmarsh](https://avatars.githubusercontent.com/u/11542164?v=4)](https://github.com/mogmarsh "mogmarsh (4 commits)")

### Embed Badge

![Health badge](/badges/alleyinteractive-wp-soft-transients/health.svg)

```
[![Health](https://phpackages.com/badges/alleyinteractive-wp-soft-transients/health.svg)](https://phpackages.com/packages/alleyinteractive-wp-soft-transients)
```

###  Alternatives

[predis/predis

A flexible and feature-complete Redis/Valkey client for PHP.

7.8k305.7M2.4k](/packages/predis-predis)[snc/redis-bundle

A Redis bundle for Symfony

1.0k39.4M67](/packages/snc-redis-bundle)[react/cache

Async, Promise-based cache interface for ReactPHP

444112.4M40](/packages/react-cache)[wp-media/wp-rocket

Performance optimization plugin for WordPress

7431.3M3](/packages/wp-media-wp-rocket)[illuminate/cache

The Illuminate Cache package.

12835.6M1.4k](/packages/illuminate-cache)[colinmollenhour/php-redis-session-abstract

A Redis-based session handler with optimistic locking

6325.6M14](/packages/colinmollenhour-php-redis-session-abstract)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
