# TagCache class · @imqueue/tag-cache

Source: https://imqueue.org/api/tag-cache/latest/tag-cache.tagcache/
Published: 2026-07-31
Author: @imqueue maintainers (https://github.com/imqueue)
Package: @imqueue/tag-cache 3.0.3 — generated reference, not hand-written

Tagged cache over redis: values are stored under their own keys, and each key is additionally added to a redis set per tag. Invalidating a tag then drops every value that was stored with it, which is what plain key-based caching cannot express — one write can be invalidated by any of several unrelated events.

The typical use is caching a computed result that depends on several entities and dropping it when any one of them changes:

```typescript
import { RedisCache } from '@imqueue/rpc';
import { TagCache } from '@imqueue/tag-cache';

const cache = new TagCache(await new RedisCache().init({ prefix: 'app' }));

await cache.set('user:1:invoices', invoices, ['user:1', 'invoices'], 60000);

// later, when user 1 changes — drops the entry above and anything else
// tagged 'user:1', whatever key it was stored under
await cache.invalidate('user:1');
```
Two things to know before relying on it. Read and write operations do NOT throw on a redis failure: they log a warning and report the failure in their return value, so a cache outage degrades to cache misses instead of taking the caller down. And the underlying redis connection is shared and owned by `RedisCache`, so [TagCache.destroy()](https://imqueue.org/api/tag-cache/latest/tag-cache.tagcache.destroy/) tears it down for every instance — see that method.

**Signature:**

```typescript
export declare class TagCache 
```

## Constructors


| Constructor | Modifiers | Description |
| --- | --- | --- |
| [(constructor)(cache)](https://imqueue.org/api/tag-cache/latest/tag-cache.tagcache._constructor_/) |  | Constructs a new instance of the `TagCache` class |


## Properties


| Property | Modifiers | Type | Description |
| --- | --- | --- | --- |
| [cache?](https://imqueue.org/api/tag-cache/latest/tag-cache.tagcache.cache/) |  | RedisCache \| undefined | _(Optional)_ The `RedisCache` this instance borrows its connection, key prefix and logger from. Deleted by [TagCache.destroy()](https://imqueue.org/api/tag-cache/latest/tag-cache.tagcache.destroy/). Documented here rather than above the constructor because it is a parameter property, and that is the only place a doc comment reaches the emitted declaration. |
| [key](https://imqueue.org/api/tag-cache/latest/tag-cache.tagcache.key/) | `readonly` | (key: string) => string | Maps a caller-supplied key onto the fully-qualified redis key, applying the prefix the underlying `RedisCache` was initialised with. Bound to that cache, so it is safe to pass around detached. |
| [logger](https://imqueue.org/api/tag-cache/latest/tag-cache.tagcache.logger/) |  | ILogger | Logger inherited from the underlying `RedisCache`. Every swallowed redis error is reported through it at warning level. |
| [redis?](https://imqueue.org/api/tag-cache/latest/tag-cache.tagcache.redis/) |  | Redis | _(Optional)_ Shared `ioredis` connection taken from `RedisCache` at construction time. Absent until `RedisCache.init()` has been awaited, and deleted again by [TagCache.destroy()](https://imqueue.org/api/tag-cache/latest/tag-cache.tagcache.destroy/) — while it is absent every operation throws a `TypeError` carrying [REDIS\_INIT\_ERROR](https://imqueue.org/api/tag-cache/latest/tag-cache.redis_init_error/). |


## Methods


| Method | Modifiers | Description |
| --- | --- | --- |
| [destroy()](https://imqueue.org/api/tag-cache/latest/tag-cache.tagcache.destroy/) |  | Destroys this cache instance Note the connection is owned by `RedisCache` and shared, so this closes it for \*\*every\*\* consumer, not just this instance — including other `TagCache` objects built from the same cache. Treat it as application shutdown rather than as releasing one instance. Afterwards this instance keeps no redis reference, so every operation on it throws a `TypeError` carrying [REDIS\_INIT\_ERROR](https://imqueue.org/api/tag-cache/latest/tag-cache.redis_init_error/). |
| [get(keys)](https://imqueue.org/api/tag-cache/latest/tag-cache.tagcache.get/) |  | Returns data stored under given keys. If a single key provided returns a single result, otherwise it will return an array of results associated with the keys Values are JSON-decoded on the way out, so what comes back is what was passed to [TagCache.set()](https://imqueue.org/api/tag-cache/latest/tag-cache.tagcache.set/), not a string. A redis failure is not thrown: it is logged as a warning and reported as `null`. That makes `null` ambiguous between "not cached" and "lookup failed", which is the right trade for a cache but means it must never be treated as proof that a value is absent. |
| [invalidate(tags)](https://imqueue.org/api/tag-cache/latest/tag-cache.tagcache.invalidate/) |  | Invalidates data under given tags Collects every key held by the given tags, deletes those keys, and then removes them from all other tag sets so no tag is left pointing at a key that no longer exists. Two properties worth knowing, because neither is obvious from the signature: - \*\*It resolves before the work is confirmed.\*\* The deletion is dispatched as a `MULTI` whose result is not awaited — a failure is logged, not returned. So a `true` result means "the invalidation was issued", not "the keys are gone". Do not use it to order a subsequent read. - \*\*The cleanup pass scans every tag\*\*, not just the ones passed in, since a key may be held by tags other than those being invalidated. Cost therefore grows with the total number of tags in the keyspace rather than with the size of `tags`. |
| [set(key, value, tags, ttl)](https://imqueue.org/api/tag-cache/latest/tag-cache.tagcache.set/) |  | Stores given value under a given key, tagging it with the given tags The value is JSON-encoded, and the key is added to one redis set per tag so [TagCache.invalidate()](https://imqueue.org/api/tag-cache/latest/tag-cache.tagcache.invalidate/) can find it later. Everything happens in a single `MULTI`, so a value is never visible without its tag membership. When `ttl` is given it is applied to the value AND refreshed on each tag set, so tag sets do not outlive the entries they track. Without it, nothing expires and the entry lives until it is invalidated. |

