Write-Through vs. Write-Back Caching Compared
AI generated
SET
TTL
Redis · Caching · Write Strategies
Write-Through vs. Write-Back Caching Compared
Synchronous against asynchronous: the consequences

Write-through writes synchronously into both cache and database, guaranteeing consistency at the cost of extra latency. Write-back only writes to the cache and delays the database write asynchronously, saving latency but creating a real risk of data loss if the cache server fails. Which strategy fits depends on the consistency requirements of the specific data.

17 min read Write-Through · Write-Back · Consistency · Latency Redis 7.x · Predis · phpredis

1. Two fundamentally different write strategies

Anyone using Redis not just for reads but also as a target for write operations has to choose between two fundamentally different strategies: write-through caching and write-back caching. Both strategies solve the same problem, namely how the cache stays current when the source data changes, but they make opposite trade-offs between consistency, latency and fault tolerance.

The fundamental difference lies in the order and synchronicity of the write operations. Write-through writes to both cache and database within the same request and waits for both confirmations before the operation counts as complete. Write-back writes only to the cache and defers the database write to a later, asynchronous step. This seemingly small shift has far reaching consequences for latency, consistency guarantees and behavior during a failure.

2. Write-through: synchronous writing in detail

In write-through caching, every write operation from the application triggers two synchronous writes: first to the database, then to Redis, or in the reverse order depending on the implementation. The application waits for confirmation from both systems before reporting the operation as successful. The result is a guarantee that many other caching strategies do not offer: cache and database are consistent at every point in time, there is no window with stale data in the cache.

The price of this guarantee is latency. Every write operation takes at least as long as the slower of the two target systems, in practice usually the database. With a typical relational database at 5 to 15 milliseconds of write latency, this time adds fully to the user's response time, and Redis barely speeds anything up here because it has to wait for the database anyway. Write-through therefore does not pay off for the write latency itself, only for the subsequent read operations, which are then guaranteed to get current data from the cache.

3. Implementing write-through in PHP

Implementing write-through in PHP follows a clear pattern: a transaction writes to the database first, and only if that step succeeded is the cache updated. If the order is reversed and the database write fails, the cache ends up holding data that does not exist in the database at all, a significantly more dangerous state than a plain cache miss.

It is also important that a failure while updating the cache does not roll back the transaction. If the database write succeeded but Redis is unreachable, the operation should still count as successful, and the stale cache entry should be actively deleted instead of erroneously updated.


<?php

declare(strict_types=1);

final class WriteThroughProductRepository
{
    public function __construct(
        private readonly \Predis\Client $redis,
        private readonly \PDO $pdo,
        private readonly int $ttlSeconds = 3600
    ) {
    }

    /**
     * Write-through update: database first, then cache, synchronously.
     */
    public function updatePrice(int $productId, float $price): void
    {
        $stmt = $this->pdo->prepare(
            'UPDATE products SET price = :price WHERE id = :id'
        );
        $stmt->execute(['price' => $price, 'id' => $productId]);

        $key = "product:{$productId}";

        try {
            $product = $this->loadFromDatabase($productId);
            $this->redis->setex($key, $this->ttlSeconds, json_encode($product));
        } catch (\Predis\Connection\ConnectionException $e) {
            // Database write succeeded; drop the stale cache entry instead
            $this->redis->del([$key]);
        }
    }

    private function loadFromDatabase(int $productId): array
    {
        $stmt = $this->pdo->prepare('SELECT * FROM products WHERE id = :id');
        $stmt->execute(['id' => $productId]);
        return $stmt->fetch(\PDO::FETCH_ASSOC);
    }
}

4. Write-back: asynchronous writing in detail

In write-back caching, sometimes also called write-behind, the application writes exclusively to Redis and reports the operation as complete immediately. The transfer to the database happens later, either through a background process that periodically synchronizes changed keys, or through a queue that processes write operations asynchronously. Redis itself briefly becomes the sole source of truth for the written data.

The advantage is dramatically lower latency, because a write operation only waits on Redis, and Redis write operations typically sit in the low single digit millisecond range, often even below that. In addition, write-back lets multiple changes to the same record be coalesced into a single database write, which drastically reduces the effective write load on the database for counters, rating points or session data. This efficiency comes at the cost of a structural risk, covered in detail in the next section.


# Write-back: write operation initially lands only in Redis
redis-cli SET counter:pageviews:4711 8420
redis-cli SADD dirty:products 4711

# Background process periodically reads the "dirty" set
redis-cli SMEMBERS dirty:products
# 1) "4711"

# After a successful DB sync, the marker is removed
redis-cli SREM dirty:products 4711

5. Implementing write-back with a queue

In practice, write-back is usually implemented with a combination of a Redis write and a separate queue that handles synchronization into the database. The application writes the new value to Redis and simultaneously marks the affected key as "dirty", for example in a Redis set. A separate worker process periodically reads this set, transfers the changes into the database, and only removes the marker after successful confirmation.

This pattern requires idempotency on the worker's side, because a crash between the database write and marker removal causes the same value to be synchronized again on the next run. For additive operations like counters this is harmless, but for absolute values like prices the worker must use "last value wins" semantics to safely handle duplicate processing.


<?php

declare(strict_types=1);

final class WriteBackSyncWorker
{
    public function __construct(
        private readonly \Predis\Client $redis,
        private readonly \PDO $pdo
    ) {
    }

    /**
     * Periodically flush dirty keys from Redis into the database.
     */
    public function flushDirtyProducts(): void
    {
        $dirtyIds = $this->redis->smembers('dirty:products');

        foreach ($dirtyIds as $productId) {
            $raw = $this->redis->get("product:{$productId}");
            if ($raw === null) {
                $this->redis->srem('dirty:products', [$productId]);
                continue;
            }

            $product = json_decode($raw, true);

            $stmt = $this->pdo->prepare(
                'UPDATE products SET price = :price WHERE id = :id'
            );
            $stmt->execute(['price' => $product['price'], 'id' => $productId]);

            // Only remove the marker after a confirmed database write
            $this->redis->srem('dirty:products', [$productId]);
        }
    }
}

6. Understanding the data loss risk in write-back

The central risk of write-back caching is data loss on a Redis server failure before the asynchronous synchronization into the database has completed. Any changes that exist only in Redis and have not yet been persisted are lost at that moment, even if Redis is configured with AOF persistence, because a window between the write operation and the disk flush always remains. This risk is the main reason write-back is not suitable for every kind of data.

The size of the risk can be controlled through the window between write operation and synchronization: a worker that synchronizes every 500 milliseconds risks losing at most 500 milliseconds worth of changes in the worst case. For counters like page views or click statistics, this risk is usually acceptable, because losing a few data points barely distorts the overall statistic. For payment data or order status the same risk is unacceptable, and write-through or a direct, synchronous database write without a cache detour is the right choice.

7. Measuring latency: the real difference

The latency difference between the two strategies can be measured directly and is often larger than developers initially assume. A write-through operation against a MySQL instance in the same data center typically sits at 8 to 20 milliseconds, dominated by the database's disk commit. A pure write-back operation against Redis is usually under one millisecond, since Redis operates in memory and the AOF flush is buffered by default.

This factor of 10 to 20 makes write-back especially attractive for high frequency write operations, such as live counters, rate limiting state or session data, where users would directly feel the latency of every single write. For rare write operations, such as an order change once a minute, the latency difference barely matters, so the additional implementation effort of write-back rarely pays off there.


# Measure Redis write latency directly
redis-cli --latency -i 1
# min: 0, max: 1, avg: 0.12 (ms) over 1 second

# Identify slow commands in the slowlog
redis-cli SLOWLOG GET 10

# Check AOF configuration, relevant for write-back risk
redis-cli CONFIG GET appendfsync
# 1) "appendfsync"
# 2) "everysec"

8. Decision criteria for practice

The choice between write-through and write-back should be made based on three questions. First: how critical is data loss for this specific data type? Financial data and order status require write-through or a direct database write, while counters and metrics can tolerate the risk of write-back. Second: how high is the write frequency? For rare write operations, the implementation effort of write-back outweighs the benefit. Third: how important is the latency of the write operation itself for the user experience?

In many real systems, both strategies run in parallel, depending on the data type. An e-commerce system typically uses write-through for orders and payment status, while product view counters and shopping cart interaction data run through write-back. This hybrid approach uses the strengths of both patterns deliberately, instead of forcing a single strategy across the entire system.


# Critical data type: write synchronously with write-through
redis-cli SET order:8842:status "paid" EX 86400

# Uncritical counter: write-back only into Redis, sync via worker
redis-cli INCR pageviews:product:4711
redis-cli SADD dirty:pageviews 4711

# Both strategies in the same system, separated by data type
redis-cli TYPE order:8842:status
redis-cli TYPE pageviews:product:4711

9. Write-through and write-back compared directly

The following table summarizes the key differences between the two write strategies and serves as a quick decision aid for practice.

Criterion Write-Through Write-Back
Write latency High, dominated by the database Low, only Redis in the critical path
Consistency Always current, no delay Briefly inconsistent until synced
Data loss risk Very low Real on Redis failure before sync
Implementation effort Low, two synchronous writes Higher, worker and idempotency needed
Typical use Orders, payment data Counters, session data, metrics

This comparison shows that there is no universally superior strategy between write-through and write-back, only a fitting choice for the given data type. Anyone who knows both patterns and combines them deliberately avoids both unnecessary latency on critical data and unnecessary data loss risk on data that should actually be written synchronously.

Mironsoft

Redis architecture, caching strategies and backend performance

Need the right write strategy for your data?

We assess your data types by consistency requirements and write frequency, and implement the right combination of write-through and write-back with clean error handling.

Data Classification

Assessing consistency requirements and risk profile per data type

Implementation

Cleanly implementing write-through and write-back with worker processes

Fault Tolerance

Deliberately reducing persistence configuration and data loss risk

10. Summary

Write-through caching and write-back caching solve the same problem with opposite trade-offs. Write-through guarantees consistency through synchronous writes to cache and database, but pays for that guarantee with latency dominated by the slower database. Write-back drastically reduces write latency by only writing Redis synchronously, but accepts a real data loss risk if Redis fails before the asynchronous synchronization completes.

The right decision depends on the specific data type: critical, consistency dependent data such as payments belongs in write-through, high frequency, loss tolerant data such as counters benefits from write-back. Most production systems combine both strategies deliberately, rather than forcing a single solution across every data type.

Write-through vs. write-back caching, the essentials at a glance

Write-Through

Synchronous writes to database and cache. Always consistent, but latency dominated by the slower database.

Write-Back

Writes only to Redis, database asynchronously via a worker. Low latency, but real data loss risk.

Decision Criterion

Assess the criticality of data loss, write frequency and latency sensitivity of the user experience.

Hybrid Use

Combine write-through for payments and orders with write-back for counters and session data.

11. FAQ: Write-Through vs. Write-Back Caching

1Fundamental difference?
Write-through writes synchronously to both systems. Write-back writes only Redis and syncs the database asynchronously later.
2Why isn't write-through faster?
The database dominates overall latency since both confirmations are awaited.
3How large is the write-back risk?
Equals the worker's sync interval, typically a few hundred milliseconds of possible data loss.
4Does persistence eliminate the risk?
No, AOF reduces it but does not fully eliminate it due to the flush window.
5What data suits write-back?
High frequency, additive data like counters, click statistics and session data.
6What data never with write-back?
Payment data and order status, write-through or a direct database write is required here.
7Duplicate processing after a crash?
Idempotency through delayed removal of the dirty marker only after a confirmed database write.
8How large is the latency difference?
Typically a factor of 10 to 20 in favor of write-back.
9Combinable in the same system?
Yes, that is the usual approach, depending on the criticality of the given data type.
10Write-behind equals write-back?
Yes, both terms describe the same pattern with asynchronous database synchronization.