IMO, you should not avoid triggers if it helps prevent invariants in your database. That is what they are especially good at preventing.
You can instruct postgres to raise exceptions using the same error code that constraints use: that way your clients do not need to know the difference.