# Assoc Replace
Ecto can call `Repo.delete/2` internally during association management, for
example through `cast_assoc/3` or `put_assoc/4` when an association uses a
delete-triggering `on_replace` strategy such as `:delete` or
`:delete_if_exists`.
Lazarus intercepts that flow:
- If the child schema has a `deleted_at` field and the parent schema does not
opt that association into `@hard_delete_on_replace`, it is **soft-deleted**
- Otherwise, it is **hard-deleted**
That means delete-triggering `on_replace` flows stay data-preserving whenever
the child schema is soft-delete-aware, but keep the default hard-delete
behaviour when they are not.
## Forcing hard-delete for specific associations
The `@hard_delete_on_replace` attribute on the parent schema **overrides** the
soft-delete behavior, forcing hard-deletion even for schemas that have
`deleted_at`.
```elixir
@hard_delete_on_replace [:ratings]
schema "posts" do
# Default: soft-deleted (Comment has deleted_at)
has_many :comments, Comment, on_replace: :delete_if_exists
# Override: hard-deleted (even though Rating has deleted_at)
has_many :ratings, Rating, on_replace: :delete_if_exists
end
```