> For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt.

# 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.

<a href="/source/services/beto/contexts/party_governance/application/commands/set_party_access_state.go.txt">Source: set_party_access_state.go</a>

```go
type SetPartyAccessStateCommandHandler struct {
	Admission  ports.Admission
	Repository ports.AuthenticationWriteRepository
}
```

Read the <a href="/source/services/beto/contexts/party_governance/application/commands/set_party_access_state.go.txt">complete handler</a>
and [Beto adaptor map](/reference/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](/reference/docs/decisions/0046-service-communication-and-composition.md).

Next: [CQRS](/learn/cqrs.md).

Adapted from the [architecture reference](/learn/attribution.md), with Pharos examples.

<details class="page-source"><summary>Page source</summary>

<a href="/source/docs/content/learn/hexagonal-architecture.md.txt">Source snapshot</a> · Revision `f928834c8`.

</details>
