SeaQL / SeaQL/sea-orm

`after_save` hook does not provide the old ActiveModel state (breaks update workflows such as file replacement)

Open
#2,814 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

2.0
Dominant language
Rust
Stars
9.9k
Forks
734
Avg merge
6h 36m
Merged PRs (30d)
8

Description

Problem Summary

In ActiveModelBehavior, the after_save hook receives only the newly saved Model.
There is no way to access the old values that the record had before the update.

This makes it impossible to implement correct update-related logic inside the ORM hook system—especially workflows where an update corresponds to a delete + insert in external systems (filesystem, caches, search indices, object stores, etc).


Why this is a real limitation

When updating something like an uploaded file, the flow is:

  • Old file path: old_path
  • New file path: new_path

The correct logic is:

  1. Save new file
  2. Update DB
  3. After update succeeds → remove old file from disk

But after_save receives only the new model, so the old_path is lost.

Logging, auditing, caching, search-index re-sync, messaging, and any "diff-style" operations cannot be done inside SeaORM because the previous values are unavailable.


Current behavior
  • before_save(self: ActiveModel) gives old values but file hasn’t been written yet & update hasn’t succeeded
  • after_save(model: Model) gives new values only old values lost
  • Adding ignored fields to ActiveModel does not work with seaography and other tools
  • SeaORM currently cannot express: "run this logic after a successful update, and also give me the old values"

What is expected / requested

It would be extremely helpful if SeaORM provided one of the following:

Option A: Pass both the old and the new model to after_save
async fn after_save<C>(
    old: Model,
    new: Model,
    db: &C,
    insert: bool
) -> Result<Model, DbErr>
Option B: Pass the old ActiveModel into after_save
async fn after_save<C>(
    old: Model,
    new: Model,
    db: &C,
    insert: bool
)
Option C: Add a new hook:

after_update(old_model, updated_model)
Separate from insert.

Option D: Provide an official "diff" mechanism

Expose the previous snapshot before update.


Why this matters

Many real-world systems require old-value access on update:

  • File uploads (delete old file after update)
  • Image processing (regenerate thumbnails)
  • Object storage cleanup
  • Search index re-sync
  • Cache invalidation
  • Logging changes
  • Webhooks or events describing what changed
  • Soft-delete recovery logs
  • Auditing systems

Without old value access, developers must move this logic outside the ORM (e.g., into resolvers or services), which defeats the purpose of having hooks.


Conclusion

This missing piece makes after_save far less useful than it could be, and forces non-atomic, non-transactional logic at higher layers of the application.

A mechanism to access the old state on update would significantly improve SeaORM for real application workflows.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by locating ActiveModelBehavior and its before_save and after_save lifecycle definitions, then trace how update state is passed through the ORM. Compare the requested hook alternatives and determine which API fits existing insert and update flows. Done means an agreed old-state mechanism is implemented with coverage for successful updates; the issue names no specific files or tests.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
database
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
28/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.