diff --git a/content/ember/v6/deprecate-ember-object-observable.md b/content/ember/v6/deprecate-ember-object-observable.md
new file mode 100644
index 00000000..f6982ea7
--- /dev/null
+++ b/content/ember/v6/deprecate-ember-object-observable.md
@@ -0,0 +1,145 @@
+---
+title: Deprecation of @ember/object/observable
+until: 7.0.0
+since: 6.5.0
+---
+
+The `get` and `set` methods from `@ember/object/observable` are deprecated. You should use native JavaScript getters and setters instead. This also applies to all built-in `Ember.Object` descendants.
+
+### Replacing `.get()`
+
+Instead of using `.get()`, you can now use standard property access.
+
+**Before**
+
+```javascript
+import EmberObject from '@ember/object';
+
+const person = EmberObject.create({
+ name: 'John Doe',
+ details: {
+ age: 30
+ }
+});
+
+const name = person.get('name');
+const age = person.get('details.age');
+```
+
+**After**
+
+```javascript
+class Person {
+ name = 'John Doe';
+ details = {
+ age: 30
+ };
+}
+
+const person = new Person();
+
+const name = person.name;
+const age = person.details.age;
+```
+
+For nested properties that might be null or undefined, use the optional chaining operator (`?.`):
+
+```javascript
+const street = person.address?.street;
+```
+
+### Replacing `.set()`
+
+Instead of using `.set()`, you can now use standard property assignment.
+
+**Before**
+
+```javascript
+import EmberObject from '@ember/object';
+
+const person = EmberObject.create({
+ name: 'John Doe'
+});
+
+person.set('name', 'Jane Doe');
+```
+
+**After**
+
+```javascript
+import { tracked } from '@glimmer/tracking';
+
+class Person {
+ @tracked name = 'John Doe';
+}
+
+const person = new Person();
+
+person.name = 'Jane Doe';
+```
+
+### A Note on Legacy Computed Properties and Setters
+
+When working with legacy computed properties, the way you set matters for reactivity.
+
+#### Updating Plain Properties
+
+To trigger reactivity (like re-computing a dependent computed property) when changing a plain property, you **must** use the `set` function. A native JavaScript assignment (`person.firstName = 'Jane'`) will change the value but will **not** trigger reactivity.
+
+```javascript
+import EmberObject, { computed, set } from '@ember/object';
+
+class Person {
+ // These properties are NOT tracked
+ firstName = 'John';
+ lastName = 'Doe';
+
+ @computed('firstName', 'lastName')
+ get fullName() {
+ return `${this.firstName} ${this.lastName}`;
+ }
+}
+
+const person = Person.create();
+console.log(person.fullName); // 'John Doe'
+
+// You MUST use `set` to update the plain property for the
+// computed property to react.
+set(person, 'firstName', 'Jane');
+
+console.log(person.fullName); // 'Jane Doe'
+```
+
+#### Updating Computed Properties with Setters
+
+In contrast, if a computed property is defined with its own setter, you **can** use a native JavaScript assignment to update it. Ember will correctly intercept this and run your setter logic.
+
+```javascript
+import EmberObject, { computed, set } from '@ember/object';
+
+class Person {
+ firstName = 'John';
+ lastName = 'Doe';
+
+ @computed('firstName', 'lastName')
+ get fullName() {
+ return `${this.firstName} ${this.lastName}`;
+ }
+ set fullName(value) {
+ const [firstName, lastName] = value.split(' ');
+ // Note: `set` is still used inside the setter itself
+ set(this, 'firstName', firstName);
+ set(this, 'lastName', lastName);
+ }
+}
+
+const person = Person.create();
+
+// You CAN use a native setter on a computed property with a setter.
+person.fullName = 'Jane Doe';
+
+console.log(person.firstName); // 'Jane'
+console.log(person.lastName); // 'Doe'
+```
+
+However, for any properties that you use directly in a Glimmer template (`{{this.myProp}}`), you should always use `@tracked` to ensure the template updates when the property changes.
diff --git a/content/ember/v6/deprecate-ember-object-observers.md b/content/ember/v6/deprecate-ember-object-observers.md
new file mode 100644
index 00000000..846321a8
--- /dev/null
+++ b/content/ember/v6/deprecate-ember-object-observers.md
@@ -0,0 +1,313 @@
+---
+title: Deprecation of @ember/object/observers
+until: 7.0.0
+since: 6.5.0
+---
+
+The `addObserver` and `removeObserver` methods from `@ember/object/observers` are deprecated. Instead of using observers, you should use tracked properties and native getters/setters.
+
+### Before
+
+```javascript
+import EmberObject from '@ember/object';
+import { addObserver, removeObserver } from '@ember/object/observers';
+
+const Person = EmberObject.extend({
+ firstName: null,
+ lastName: null,
+
+ fullName: null,
+
+ fullNameDidChange: function() {
+ this.set('fullName', `${this.get('firstName')} ${this.get('lastName')}`);
+ }.observes('firstName', 'lastName'),
+});
+
+let person = Person.create({ firstName: 'John', lastName: 'Doe' });
+
+addObserver(person, 'fullName', () => {
+ console.log('Full name changed!');
+});
+
+person.set('firstName', 'Jane');
+
+removeObserver(person, 'fullName', null, 'fullNameDidChange');
+```
+
+### After
+
+```javascript
+import { tracked } from '@glimmer/tracking';
+
+class Person {
+ @tracked firstName;
+ @tracked lastName;
+
+ get fullName() {
+ return `${this.firstName} ${this.lastName}`;
+ }
+
+ constructor(firstName, lastName) {
+ this.firstName = firstName;
+ this.lastName = lastName;
+ }
+}
+
+let person = new Person('John', 'Doe');
+console.log(person.fullName); // John Doe
+
+person.firstName = 'Jane';
+console.log(person.fullName); // Jane Doe
+```
+
+### Handling Observers with Side Effects
+
+Observers are sometimes used to trigger side effects, such as logging or making a network request, when a property changes. The modern approach is to encapsulate these side effects in methods that are called explicitly.
+
+**Before: Observer with a Side Effect**
+
+```javascript
+import EmberObject from '@ember/object';
+
+const User = EmberObject.extend({
+ username: null,
+ lastLogin: null,
+
+ lastLoginChanged: function() {
+ console.log(`User ${this.get('username')} logged in at ${this.get('lastLogin')}`);
+ }.observes('lastLogin')
+});
+
+const user = User.create({ username: 'johndoe' });
+user.set('lastLogin', new Date()); // This triggers the observer
+```
+
+**After: Explicit Method for the Side Effect**
+
+With modern class-based components, you would create a method that updates the property and performs the side effect. This makes the code's behavior much clearer.
+
+```javascript
+import { tracked } from '@glimmer/tracking';
+
+class User {
+ @tracked username;
+ @tracked lastLogin;
+
+ constructor(username) {
+ this.username = username;
+ }
+
+ // An explicit action that updates the property and causes the side effect
+ login() {
+ this.lastLogin = new Date();
+ this.logLogin();
+ }
+
+ logLogin() {
+ console.log(`User ${this.username} logged in at ${this.lastLogin}`);
+ }
+}
+
+const user = new User('johndoe');
+user.login(); // Call the method to trigger the update and the side effect
+```
+
+### Replacing Observers with Modifiers
+
+In legacy components, observers were often used to react to changes in component arguments (`@args`). This pattern can now be replaced with modifiers, which provide a cleaner, more reusable, and more idiomatic way to manage side effects related to DOM elements and argument changes.
+
+**Before: Observer on a Component Argument**
+
+Here is an example of a classic component that uses an observer to update a third-party charting library whenever its `data` argument changes.
+
+```javascript
+// Classic Component JS
+import Component from '@ember/component';
+import { observer } from '@ember/object';
+import Chart from 'chart.js'; // A third-party library
+
+export default Component.extend({
+ tagName: 'canvas',
+ chart: null,
+
+ // 1. Create the chart when the element is inserted
+ didInsertElement() {
+ this._super(...arguments);
+ this.chart = new Chart(this.element, {
+ type: 'bar',
+ data: this.get('data')
+ });
+ },
+
+ // 2. Observe the 'data' property for changes
+ dataDidChange: observer('data', function() {
+ if (this.chart) {
+ this.chart.data = this.get('data');
+ this.chart.update();
+ }
+ }),
+
+ // 3. Clean up when the component is destroyed
+ willDestroyElement() {
+ this._super(...arguments);
+ if (this.chart) {
+ this.chart.destroy();
+ }
+ }
+});
+```
+
+**After: Using a Modifier**
+
+In modern Ember, this logic can be encapsulated in a modifier. The modifier has direct access to the element and can react to argument changes, handling setup, updates, and teardown cleanly.
+
+First, create a modifier file:
+
+```javascript
+// app/modifiers/update-chart.js
+import { modifier } from 'ember-modifier';
+import Chart from 'chart.js';
+
+export default modifier(function updateChart(element, [data]) {
+ // This function runs whenever `data` changes.
+
+ // Get the chart instance, or create it if it doesn't exist.
+ // Storing the instance on the element is a common pattern.
+ let chart = element.chart;
+
+ if (!chart) {
+ // Create chart on first render
+ chart = new Chart(element, {
+ type: 'bar',
+ data: data
+ });
+ element.chart = chart;
+ } else {
+ // Update chart on subsequent renders
+ chart.data = data;
+ chart.update();
+ }
+
+ // The return function is a destructor, which handles cleanup.
+ return () => {
+ if (element.chart) {
+ element.chart.destroy();
+ element.chart = null;
+ }
+ };
+});
+```
+
+Then, use this modifier in your Glimmer component's template:
+
+```hbs
+{{! The component template }}
+
+```
+
+This approach is much cleaner because:
+1. The logic is reusable and not tied to a specific component.
+2. It clearly separates the component's data and template from the DOM-specific logic.
+3. The modifier's lifecycle (setup, update, teardown) is managed by Ember, making it more robust.
+
+### Replacing Observer-Based Waiting Patterns
+
+Sometimes observers were used not just to mirror state into another property or invoke a side effect immediately, but to "wait" until a property reached a certain condition (e.g. became non-null / a flag flipped) and then continue logic. Instead of wiring an observer that removes itself when the predicate passes, choose one of these approaches:
+
+#### 1. Prefer Reactive Rendering (Often You Need Nothing Extra)
+
+If the goal is just to show different UI when something becomes ready, branch in the template:
+
+```hbs
+{{#if this.isReady}}
+
+{{else}}
+
+{{/if}}
+```
+
+`this.isReady` should be a `@tracked` property (or derived from other tracked state). No explicit watcher is required; changes trigger re-render automatically.
+
+#### 2. requestAnimationFrame Polling (UI-Frame Cadence)
+
+Use when a rapidly changing UI-related value will settle soon and you want per-frame checks without observers:
+
+```js
+export class RafWaiter {
+ constructor(object, key, predicate, callback, { maxFrames = Infinity } = {}) {
+ this.object = object;
+ this.key = key;
+ this.predicate = predicate;
+ this.callback = callback;
+ this.maxFrames = maxFrames;
+ this._frame = 0;
+ this._stopped = false;
+ }
+
+ start() {
+ const tick = () => {
+ if (this._stopped) return;
+ let value = this.object[this.key];
+ if (this.predicate(value)) {
+ this.callback(value);
+ this.stop();
+ return;
+ }
+ if (++this._frame < this.maxFrames) {
+ this._rafId = requestAnimationFrame(tick);
+ }
+ };
+ tick(); // initial synchronous check
+ return () => this.stop();
+ }
+
+ stop() {
+ this._stopped = true;
+ if (this._rafId) cancelAnimationFrame(this._rafId);
+ }
+}
+
+// Usage:
+// const cancel = new RafWaiter(model, 'isReady', v => v === true, value => doSomething(value)).start();
+```
+
+#### 3. ember-concurrency Task (Interval / Backoff Friendly)
+
+Provides structured cancellation and adjustable cadence; integrate with destruction for safety.
+
+```js
+import { task, timeout } from 'ember-concurrency';
+import { registerDestructor } from '@ember/destroyable';
+
+class WaitServiceLike {
+ constructor(object) {
+ this.object = object;
+ registerDestructor(this, () => this.waitFor?.cancelAll?.());
+ }
+
+ waitFor = task(async (key, predicate, { interval = 50, maxChecks = Infinity } = {}) => {
+ let checks = 0;
+ while (checks < maxChecks) {
+ let value = this.object[key];
+ if (predicate(value)) {
+ return value;
+ }
+ checks++;
+ await timeout(interval);
+ }
+ throw new Error('Condition not met before maxChecks');
+ });
+}
+
+// Usage:
+// let waiter = new WaitServiceLike(model);
+// let result = await waiter.waitFor.perform('isReady', v => v === true, { interval: 30 });
+```
+
+#### Choosing an Approach
+
+- Template branching: simplest; no manual cleanup.
+- `requestAnimationFrame`: sync with paint loop for short-lived UI readiness waits.
+- `ember-concurrency` task: tunable intervals, cancellation, good for async processes.
+
+Avoid reimplementing implicit observer semantics. Favor explicit state + rendering or cancellable tasks.