# moize: a thorough memoization library that asks you to move on

> moize is a JavaScript memoization library with an unusually wide options surface, cache statistics, direct cache manipulation and a dozen shortcut methods, but the README opens by declaring the project deprecated in favour of micro-memoize, which the author says covers most of the functionality at nearly half the size and better speed. It is worth reading as a study in cache configuration rather than as a dependency to add.

**planttheidea/moize** — The consistently-fast, complete memoization solution for JS

- Repository: https://github.com/planttheidea/moize
- Website: https://planttheidea.github.io/moize/
- Stars: 914 · Forks: 19
- Language: TypeScript
- License: MIT
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/planttheidea-moize

## The deprecation notice is the first thing in the README

moize is a memoization library for JavaScript, and the first element of the README is a caution block. It states that the library has been deprecated in favour of micro-memoize, which as of version 5 incorporates most of the functionality that moize offers at nearly half the size and better speed. It recommends migrating to micro-memoize at latest, and points at a migration guide, MIGRATION.md, in the repository for the specific changes to a codebase.

That framing changes how the rest of the README should be read. Everything after the caution is a specification of a library that its own author would rather you stopped using, which is exactly why it is still interesting: it is a complete catalogue of the ways memoization behaviour can be tuned, written down by someone who has thought about the options hard enough to enumerate them.

The positioning is otherwise confident. moize describes itself as a consistently blazing fast memoization library that handles multiple parameters, including default values, without any additional configuration, and offers a large number of options to satisfy any number of potential use cases. The badge claims full test coverage, and the repository does contain a __tests__ directory and a benchmark directory.

The library is MIT licensed, written in TypeScript, and the last push was on 2026-10-14, so the deprecation is a decision about direction rather than an abandonment.

## How the cache key is built, and why defaults matter

The usage example is short, and it shows the whole contract.

```ts
import moize from 'moize';

const method = (a: number, b: number) => a + b;

const memoized = moize(method);

memoized(2, 4); // 6
memoized(2, 4); // 6, pulled from cache
```

The second call with the same arguments comes from the cache. The important detail is that this works with no configuration at all, because moize builds the key from all the parameters passed, including their default values.

That last clause is the whole difference between a memoization library and a hand written cache. A hand written cache typically keys on the arguments you remember to include, which is why the same function called with the same effective arguments but a different explicit default hits the underlying function again. Handling default values as part of the key means the cache is correct by default rather than correct if you configure it.

All parameter types are supported, including circular objects and functions, which matters because the default key comparison is by reference and circular structures are where naive implementations fall over.

The options can be passed inline as the second argument, or curried so that the options come first.

```ts
// inline
moize(fn, options);

// curried
moize(options)(fn);
```

## Twenty options, and the ones that decide your cache semantics

The options type is the specification of the library, and it is worth reading in full because each option answers a question you would otherwise have to answer yourself.

The equality family is the first group. isDeepEqual compares each key argument by deep equality, isShallowEqual does the same one level deep, matchesArg is a custom comparison between two key arguments, and matchesKey is a custom comparison across all key arguments. The default is none of them, which means reference equality.

The size and lifetime group is maxSize for the maximum size of the cache, maxAge for the milliseconds before an entry expires, maxArgs for the maximum number of arguments used to build the key, and updateExpire, which refreshes an entry's expiration when it is hit. updateCacheForKey goes further and calls the underlying function again with the same parameters to refresh the stored value.

The key building group is serializer, which turns the arguments into a string key, and transformArgs, which reshapes the arguments before they are stored as the key. isSerialized switches the parameters to be serialized rather than directly referenced.

Two options describe the kind of function being memoized: isPromise and isReact. isReact matters because a React component must not be treated as a plain value, and isPromise because a promise is a mutable object whose identity should not be the cache key.

Then there is the observer group. onCacheAdd fires when an entry is added, onCacheHit when an existing entry is used, onCacheChange when either an entry is added or the LRU ordering of the cache has changed, and onExpire fires when an entry expires in combination with maxAge. Each callback receives the cache, the options and the memoized method, so an observer can be attached to any memoized function without wrapping it.

Finally profileName gives the memoized method an identifier for statistics collection, and all the default values live in src/constants.ts.

## Shortcut methods and the hook

Because the options type is large, the library provides shortcut methods that preset the common combinations.

The list in the README includes moize.deep, which is the isDeepEqual option in method form, moize.shallow for shallow equality, moize.promise and moize.react for the promise and React cases, moize.serialize and moize.serializeWith for the serialization options, moize.maxAge, moize.maxArgs and moize.maxSize for the cache bounds, moize.matchesArg and moize.matchesKey for the custom comparisons, moize.transformArgs and moize.updateCacheForKey for the key and refresh behaviours, moize.infinite for a cache that does not expire, and moize.profile for the statistics identifier.

For React users there is a useMoize hook, which is the point where the library touches a framework rather than staying framework agnostic.

The composition section covers combining memoized functions, and the practical rule there is the one people get wrong most often: if you memoize a function whose arguments include another memoized function, the outer cache can hold stale references to inner functions. Composition is where you need to think about which layer owns the identity.

Overall, the option surface is what makes this library educational. Each shortcut is a named answer to a question you would otherwise answer by reading the implementation.

## Statistics, introspection and reaching into the cache directly

Three groups of API exist for people who need to see what the cache is doing.

Statistics are collected with collectStats, read with getStats, optionally for a single profile name, and cleared with clearStats. Because stats are opt-in per memoized function through the profileName option, the overhead is only paid where you ask for it. The stats methods are listed separately from the ordinary methods, which suggests they live on a different object rather than on the memoized function itself.

Introspection is two functions. isCollectingStats tells you whether statistics are currently being gathered, and isMoized tells you whether a given value is a memoized function.

Direct cache manipulation is the third group, and it is the one that separates moize from a simpler cache. The cache property gives you the underlying cache, and cacheSnapshot gives you a snapshot of it. From there you can add a key and value, get the value for a key, check whether a key exists, list keys and values, remove a key, update the value for a key, clear the entire cache, and read the cache statistics.

That is a lot of surface for a memoization helper, and it is also the reason the library is bigger than its successor. The author says micro-memoize covers most of the functionality at nearly half the size, which implies the features dropped are the peripheral ones, and the migration guide is the place to find out exactly which.

## Packaging, import paths and the browser targets

The package installs like any other npm package.

```bash
npm i moize --save
```

There are three documented import paths, and the distinction matters because the browser and the Node builds are not the same file.

```ts
import moize from 'moize';
```

```ts
import moize from 'moize/mjs/index.mjs';
```

```ts
const moize = require('moize');
```

The first is ESM in browsers, the second is ESM in NodeJS and points at an explicit mjs entry, and the third is CommonJS. The browser field in the manifest points at dist/moize.js, which is the bundled build.

The browser targets are declared in the browserslist field and are noticeably old: defaults, Explorer 9 and above, Safari 6 and above, Opera 15 and above, iOS 8 and above, and Android 4 and above. That is a deliberate statement about the audience, and it is the kind of thing that survives in a manifest for years without anyone revisiting it.

The build is Babel and Rollup, with a webpack directory, an es-to-mjs.js helper and jest for the tests. The TypeScript definitions are shipped as index.d.ts at the root of the repository, and the package has two dependencies, fast-equals for the deep and shallow equality comparisons and micro-memoize at version 4.2.0, which is the library the README now tells you to migrate to.

The repository also carries a docs directory, a DEV_ONLY directory, a CHANGELOG.md and two release configuration files, one for the stable line and one for the beta line.

## Release numbering that tells you about the beta line

The release history is a little unusual and worth reading carefully.

The recent releases are v6.1.7 from 2025-11-30, v6.2.0-beta.1 from 2025-09-22 and v6.2.0-beta.0 from the same day. So the 6.2 betas shipped in September 2025 and the stable line then moved on with a 6.1.7 patch release in November 2025, which is the opposite of the usual order where a beta precedes its stable release in time.

That pattern is consistent with the deprecation. The 6.2 beta line was an experiment that was released, and the stable line continued to receive maintenance releases afterwards. If you are pinning a version today, the sensible choices are the last stable release on the 6.1 line, or, as the README advises, the latest micro-memoize.

The changelog is at the root of the repository, the releases are managed with release-it, given the .release-it.json and .release-it.beta.json configuration files, and the project homepage is planttheidea.github.io/moize.

For an engineer, the practical summary is short. moize is a well documented and thoroughly configurable memoization library that its author has decided should not be adopted, and the documentation remains one of the better written descriptions of what memoization options actually mean.

## Conclusion

Adopt micro-memoize rather than moize for any new work, because the author has deprecated moize in favour of it and says the newer library covers most of the same ground at nearly half the size with better speed. Use moize itself only if you are migrating an existing codebase and want a reference implementation to compare against, or if you depend on a specific feature such as the statistics collection and the direct cache manipulation API. Before you start a migration, read MIGRATION.md in the repository, since the two libraries do not have identical option names, and check which version of micro-memoize you install, because the recommendation names version 5 specifically.

## FAQ

### Is moize still maintained?

The library has been deprecated in favour of micro-memoize, which the author says incorporates most of its functionality at nearly half the size and better speed. The last push was on 2026-10-14, so the repository is still receiving work, but the recommendation is to migrate.

### How do I install and import moize?

Run npm i moize --save. The import depends on the environment: import moize from 'moize' for ESM in browsers, import moize from 'moize/mjs/index.mjs' for ESM in NodeJS, and const moize = require('moize') for CommonJS.

### What options does moize accept for cache behaviour?

The options cover equality (isDeepEqual, isShallowEqual, matchesArg, matchesKey), cache bounds and lifetime (maxSize, maxAge, maxArgs, updateExpire, updateCacheForKey), key building (serializer, transformArgs, isSerialized), function kind (isPromise, isReact), observers (onCacheAdd, onCacheHit, onCacheChange, onExpire) and the statistics identifier profileName. Defaults are in src/constants.ts.

### How do I collect statistics about a memoized function?

Give the memoized method a profileName, then use the statistics methods: collectStats to start collecting, getStats to read them, optionally for a single profile name, and clearStats to reset. The isCollectingStats and isMoized helpers report on the current state.

### What should I use instead of moize?

The README recommends micro-memoize at latest, noting that version 5 incorporates most of the functionality moize offers at nearly half the size and better speed. A MIGRATION.md file in the repository covers the specific changes needed in an existing codebase.

## Sources

- [License: MIT](https://github.com/planttheidea/moize/blob/master/LICENSE)
- [planttheidea/moize on GitHub](https://github.com/planttheidea/moize)
- [Project website](https://planttheidea.github.io/moize/)
- [README](https://github.com/planttheidea/moize/blob/master/README.md)
- [Releases](https://github.com/planttheidea/moize/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/planttheidea-moize
