Haeminway haeminway
한국어
Back to Tech Notes
1 min read

PropertiesService Is Not a Database: the 9KB Wall

A Properties value caps near 9KB. Cache only data you can lose. Big state goes to Sheet, Drive, or an external DB. Plain JSON loses types.

PropertiesService is a small store, not a database. Each value caps near 9KB, and the whole store is limited too. Keep a cursor, small config, or an idempotency key there; send anything bigger elsewhere.

Why it matters

Start with “store state as JSON in Properties” and one day, when the data grows, it silently fails at 9KB. And state kept only in cache disappears when the TTL expires. Putting data you can’t lose into volatile storage is where the accident begins.

Storage choice rule

StoreUseLimit
CacheServiceDisposable acceleration cache100KB/key, TTL-based
PropertiesServiceCursors, config, flags~9KB/value
SheetUser-visible tabular state50,000 chars/cell
Drive JSONLarger opaque state (manage the file)File size
External DBMulti-user, query-heavy, high-volume

The key question: can the data be lost? That answer splits CacheService from the rest.

Plain JSON loses types

JSON.stringify()/parse() alone won’t safely restore Date, Map, Set, undefined, or NaN.

// store Date as an ISO string, restore on read
const replacer = (k, v) => (v instanceof Date ? { __d: v.toISOString() } : v);
const reviver = (k, v) => (v && v.__d ? new Date(v.__d) : v);

props.setProperty("job", JSON.stringify(state, replacer));
const state = JSON.parse(props.getProperty("job") || "{}", reviver);

Deeper: chunk caches over 100KB

One CacheService key caps at 100KB. For larger values, split into chunks across keys with a reassembly key. And a cache must always have a recompute path.

One line to keep: small → Properties, disposable → Cache, big → Sheet/Drive/DB. Protect types with a replacer/reviver.

Frequently asked questions

Why does storing JSON state in PropertiesService silently fail?
Each value caps near 9KB, so as data grows it fails without a clear error. Keep only a cursor, small config, or an idempotency key there; send larger state to Sheet, Drive, or an external DB.
When should I use CacheService versus PropertiesService?
CacheService (100KB per key, TTL-based) is for disposable acceleration data you can afford to lose. PropertiesService (about 9KB per value) is for durable cursors, config, and flags.
Which JavaScript types does plain JSON serialization fail to restore safely?
Date, Map, Set, undefined, and NaN are not safely restored by JSON.stringify/parse alone. Use an explicit replacer and reviver to protect those types.