Say you run an e-commerce site and need an audit trail of every price change on the products table for compliance. You create an AFTER UPDATE row-level trigger. When a price changes, the trigger compares OLD.price and NEW.price, and if they differ it inserts a row into price_history with the old value, the new value, the product id, and now().
Now it does not matter whether the price was changed by the admin dashboard, a bulk import, or a developer running a one-off UPDATE in psql at 2 AM. The history table fills itself, the original UPDATE and the history INSERT either both commit or both roll back, and no application code had to remember to log anything.
A second classic use is enforcing a constraint a plain CHECK cannot express, like preventing an order from being marked shipped before it is paid. A BEFORE UPDATE trigger inspects the row and raises an exception if NEW.status is shipped while NEW.paid_at is null, blocking the bad write at the source.