I think that SERIALIZABLE should be the default eventually, but others may disagree and I won't make a prediction.
However, it isn't necessary to solve the problem. It would be relatively easy to use a row lock in this case to solve the problem, as well, but I like to avoid those unless there's a reason.
If you want to have a mix of SERIALIZABLE and other transactions, or you are worried about making a mistake (or some malicious user), then you need to use the row lock. Eventually there should be a way to force users into serializable transactions.
EDIT: actually, in the trigger, you could explicitly check if the transaction isolation mode is serializable. That would be the best approach:
if current_setting('transaction_isolation') <> 'serializable' then
raise exception 'serializable mode required';
end if;
However, it isn't necessary to solve the problem. It would be relatively easy to use a row lock in this case to solve the problem, as well, but I like to avoid those unless there's a reason.
If you want to have a mix of SERIALIZABLE and other transactions, or you are worried about making a mistake (or some malicious user), then you need to use the row lock. Eventually there should be a way to force users into serializable transactions.
EDIT: actually, in the trigger, you could explicitly check if the transaction isolation mode is serializable. That would be the best approach: