Choosing Tracked Properties vs Classic Computed Properties in Ember Octane
Decide between @tracked properties and classic computed properties in Ember Octane. Compare trade‑offs, constraints, and see a concrete example of a tracked component with an action.
10 Oct 2026, 09:51 UTC

Decision: Which Reactive Feature to Use?
When refactoring an Ember app to Octane, you must decide how to express reactive state. Two supported patterns exist:
- @tracked properties – native class property decorator that signals Ember’s reactivity system.
- Classic computed properties – legacy getter/setter syntax that explicitly lists dependencies.
Constraints to Consider
- Ember CLI
ember-sourceversion must be3.20or newer to support native classes and decorators. - Babel 7+ with
@babel/plugin-proposal-decorators(orember-cli-babel) is required. - TypeScript users need
@ember/decoratorsv0.10.0+ for proper type inference. - Server‑side rendering (SSR) requires careful handling of tracked state during the initial render.
- Classic computed properties still exist in the codebase; mixing both can lead to maintenance headaches.
Trade‑Off Comparison
| Aspect | @tracked Property | Classic Computed Property |
|---|---|---|
| Syntax | | |
| Boilerplate | Minimal – one decorator line per reactive value. | Higher – getters, setters, and dependency lists. |
| Reactivity | Automatic – any mutation to a tracked primitive triggers updates. | Manual – must list dependencies; missing one breaks reactivity. |
| Performance | Efficient – only the touched property triggers re‑render. | Potentially heavier – recomputes when any listed dependency changes. |
| TypeScript Support | Strong – decorators provide type inference. | Weaker – computed properties are less type‑safe. |
| Deprecation Risk | Low – Octane’s core feature. | High – classic computed properties are legacy and may be removed in future major releases. |
| Server‑Side Rendering | Requires careful use of this.count during render; tracked state is serializable. | Works out of the box but can be slower if many computed properties exist. |
When to Prefer @tracked
- Simple, mutable state that changes in response to user actions or async responses.
- When you want minimal boilerplate and a clean, declarative API.
- In components, services, or routes that manage local UI state.
When Classic Computed Is Still Useful
- Complex derived values that depend on multiple unrelated properties.
- When you need fine‑grained control over when a value recomputes.
- Legacy codebases where refactoring to tracked would be risky or time‑consuming.
Concrete Implementation Example
Component Using @tracked and @action
// app/components/counter.js
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { action } from '@ember/object';
export default class CounterComponent extends Component {
@tracked count = 0;
@action
increment() {
this.count += 1;
}
}
Template
// app/templates/components/counter.hbs
Increment
Current count: {{this.count}}
Testing the Reactive Flow
- Run
ember test --filter counterto ensure the component renders and the button increments the count. - Verify that the test fails if
this.countis not marked@tracked– the template will not update. - Check the Ember CLI version with
ember-cli --version; it should report3.20+or newer.
Validating the Decision
- Static Analysis: Use
ember-cli-babelto confirm decorators are transpiled correctly. - Runtime Check: In the browser console, log
this.countinside the component; updating it should trigger a re‑render observable in the DOM. - Performance Profiling: Use Ember Inspector’s “Performance” tab to compare re‑render counts between a tracked property and a computed property in a similar scenario.
Rollback Considerations
Switching from a computed property to a tracked property changes only the JavaScript file; the template remains identical. However, if the computed property had side effects (e.g., logging or fetching), those must be migrated into the action or a separate service. Always run the full test suite after the change to catch regressions.
Conclusion
For new Ember Octane projects, @tracked and @action provide a lightweight, type‑safe, and future‑proof approach to reactive state. Classic computed properties are still viable for legacy code or complex derived values, but they carry higher maintenance risk and slower performance in many cases.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.