# Hexagonal architecture: ports and adaptors Hexagonal architecture exposes meaningful application interactions and expresses external needs through ports. Adaptors connect those capabilities to technologies. Source dependencies point towards application and domain policy. ## Ports describe capabilities | Role | Pharos example | | --- | --- | | Driving adaptor | Broker request decoding and authenticated caller mapping | | Inbound capability | SetPartyAccessState application operation | | Outbound port | AuthenticationWriteRepository | | Driven adaptor | Party-owned PostgreSQL persistence | | Composition root | Service startup that binds ports and manages workers | A port can be an interface, protocol, function or public method. Define it around a meaningful capability. An application call reaches a concrete adaptor at runtime; the application's source depends on its port contract. ```mermaid flowchart LR Broker[Broker adaptor] --> Handler[Application handler] Handler --> Aggregate[PartyAuthentication] Handler --> Port[Write repository port] Postgres[PostgreSQL adaptor] -. implements .-> Port ``` ## Follow an actual handler The handler checks admission, loads its target, invokes aggregate behaviour and saves a material change. The surrounding transaction machinery owns commit and receipt bookkeeping. The handler receives ordinary context, command and port values. Read the [complete handler](../../../services/beto/contexts/party_governance/application/commands/set_party_access_state.go) and [Beto adaptor map](../../../services/beto/adaptors/README.md). External provider observations are acquired and validated at their owning boundaries before the aggregate transaction applies them. ## Composition and lifecycle Dependency injection supplies collaborators. Composition roots choose concrete implementations and own their lifecycle. Resolve the graph before workers start; drain workers before disposing of their resources. Clean up partial startup. An in-memory fake can show which port the handler calls. A real PostgreSQL test establishes transaction and concurrency behaviour. These are different claims with different evidence. Read [the composition decision](../../decisions/0046-service-communication-and-composition.md). Next: [CQRS](cqrs.md). Adapted from the [architecture reference](attribution.md), with Pharos examples.