Glimmer Internals At a Glance

Why Templates Update Surgically

Glimmer Internals At a Glance

Glimmer is Ember's rendering engine. It compiles templates to bytecode and uses a tag-based reactivity system to update only what changed.

4 min read Level 3/5 #ember#glimmer#internals
What you'll learn
  • Know that Glimmer compiles templates to opcodes
  • Understand that tags track reactive reads
  • Recognize that each tracked write bumps a revision counter

You don’t need Glimmer’s internals to ship features, but understanding the shape of it helps explain why Ember feels fast and why @tracked works the way it does.

Templates Become Bytecode

At build time, Glimmer parses every .hbs file into a wire format and then into compact opcodes. At runtime, a VM walks those opcodes to build the DOM. This is why template syntax is strict — it has to be statically analyzable.

Tag-Based Reactivity

Every reactive value (a @tracked field, an Ember Data record, a service property) has a small object called a tag. Reading the value records the current tag; writing the value bumps a global revision counter.

// rough mental model
let revision = 0;

class Tag {
  rev = ++revision;
  bump() { this.rev = ++revision; }
}

A getter like get total() { return this.count + 1 } records that it depends on count’s tag. Between frames, Glimmer asks: have any of the tags this DOM node depends on changed revision? If not, skip it.

Only The Affected DOM Updates

Because reads are tracked at the field level, a <h1>{{@title}}</h1> only re-renders when something writes @title. Sibling nodes that read other values keep their bytecode validated and stay untouched.

Practical Takeaways

  • Use @tracked on raw fields. Replace arrays/objects rather than mutating.
  • Lean on getters; they are cached as long as their tag dependencies are stable. Add @cached for expensive ones.
  • Don’t reach for manual change detection — there is none. Reactivity is pull-based from the renderer’s perspective.
Ember Data — The Data Layer →