Integration Test Boundary
The deliberate choice of what a test includes and what it stubs, which determines both what the test can detect and what it costs.
"Integration test" means so many different things that teams routinely argue past each other. The useful move is to stop using the label and state the boundary: what real components are inside the test, and what is replaced.
Common boundaries, in increasing scope: the service with a real database and everything else stubbed, which catches the large class of defects that live in queries, migrations, transactions and mapping — usually the highest-value integration test available. The service with real database and real message broker, which adds serialisation and consumer behaviour. Two services together, which is where cost begins to outrun value and where contract tests are the better instrument. And the full system, which belongs to the small curated end-to-end set.
Containerised dependencies made the first of these cheap enough that using an in-memory substitute for the database is now hard to justify — the substitute has different SQL semantics, different transaction behaviour and a different query planner, so it verifies code against a database you do not run.
The rule of thumb: put the boundary just outside the code you own, and use contracts rather than live calls for anything owned by another team.