Learn when Clojure's interned keywords and other shared values act like flyweights, where that saves memory or comparison cost, and where it becomes a dangerous over-optimization.
Flyweight pattern: A structural pattern that shares common intrinsic data so many objects or values do not each need their own full copy.
Flyweight shows up in Clojure more as a property of chosen representations than as a formal factory object. Keywords, symbols, enum-like values, and shared static lookup maps can all behave like flyweights because the program reuses one small representation instead of allocating repeated equivalent data everywhere.
Clojure keywords are interned, which means the runtime reuses one keyword object for the same textual keyword value. That makes them useful for:
:pending or :activeThis is one reason keywords are such a good fit for domain labels and status fields.
The pattern is strongest when many values share the same intrinsic part and differ only in extrinsic context.
Examples:
The program stores one shared representation of the repeating part and keeps the unique context elsewhere.
The common mistake is to over-apply the idea. Flyweight is useful when repeated values truly dominate the representation cost. It is not a blanket excuse to turn every string into a keyword or every structure into a cached singleton.
In particular, do not keywordize arbitrary unbounded user input. Keywords are interned, so creating endless new ones from uncontrolled data can produce long-lived memory growth.
Use keywords for:
Prefer strings or ordinary data for:
Flyweight in Clojure can also mean reusing a shared lookup table or configuration map instead of rebuilding equivalent structures per request.
That is often a higher-value optimization than worrying about one extra keyword allocation. Representation reuse should target the real hot path or repeated heavy structure, not just what sounds clever.
That is one reason flyweight in Clojure is often a representation choice rather than a factory pattern. The biggest wins frequently come from choosing one shared immutable table or canonical value set that many paths can reuse safely.
This is one of the most common ways to misuse flyweight-like reasoning in Clojure.
If memory or allocation pressure has not actually been observed, a flyweight rewrite may add complexity for little gain.
Flyweight works well in Clojure partly because shared values are immutable. That does not mean you should build global mutable registries for ordinary data.
Use interned keywords and other shared immutable values for bounded, repeated intrinsic data. Measure before optimizing, and do not turn arbitrary external strings into process-lifetime identifiers. In Clojure, flyweight is most useful when it emerges naturally from good representation choices rather than from elaborate allocation tricks.