Start here. This is the direct spoken answer to practice first.
Why this question matters
The inbox records which messages a particular consumer has applied. Its value comes from sharing a transaction with the business change, not from performing a separate check before the handler runs.
I use a stable source event id and store an inbox row scoped to the consumer, for example (ConsumerName, MessageId). The handler inserts that row and applies the business change in the same database transaction. A unique constraint resolves concurrent duplicate deliveries: one transaction succeeds and the other recognizes the existing message. Recording the inbox row before or after the business change in separate commits would create either lost work or duplicate effects.