schedule-effective-dated-changeslisted
Install: claude install-skill kennguyen887/agent-foundation
# Schedule effective-dated changes
Applying a change at a **future effective date** (plan/tier/price changes, scheduled deactivations,
end-of-billing-cycle updates) without mutating now. The Redis *delayed job* alternative (and the cron +
overlap lock) is `background-jobs-and-caching`; transactions are `write-service-code` §9.
## Core principle
**Persist the *intended change* as a row with an effective date — don't mutate now, and don't bury the
timer in memory.** A pending-changes table makes a future change **queryable** ("what's scheduled?"),
**cancellable** (the user changes their mind), and **auditable** (history of what applied when). A
scheduled sweep applies the **due** ones transactionally and records history.
## 1. Store the intent, not the mutation
A `pending_changes` table holds the change payload + when it takes effect + its lifecycle status —
instead of writing the change to the live row immediately:
```ts
@Entity() class PendingChange extends BaseEntity {
@Column() targetId!: string; // the entity to change
@Column({ type: 'jsonb' }) data!: ChangePayload; // WHAT changes (new tier, new price, …)
@Column() effectiveAt!: Date; // WHEN it takes effect
@Column({ type: 'enum', enum: PendingStatus, default: PendingStatus.PENDING }) status!: PendingStatus;
@Column({ nullable: true }) reason!: Nullable<string>; // why it FAILED / was CANCELLED
}
// PENDING → COMPLETED | FAILED | CANCELLED
```
Now "show my scheduled change