Example Contracts¶
Copy-ready contracts for common services: databases, a message broker, a proxy, a cron job and more. Start from the one closest to your service, or use them as dependencies. New to writing contracts? Read the developer guide first.
Tip
A contract describes what a service exposes and how it behaves. Deployment details stay in your manifests. A contract points at the specs you already have (OpenAPI, AsyncAPI, a gRPC descriptor, JSON Schema for configurations) and adds what they lack: owner, dependencies, compatibility and state. Every referenced spec file must parse as JSON or YAML (see interface types).
To see contracts in action, try a demo:
- Live dashboard demo: the dashboard in your browser, nothing to install. Its source is in
examples/demo. Its runtime conformance finding is recorded. - Docker Compose demo: a registry, an Evidence Server and the dashboard on your machine, from one OCI artifact. A host agent checks runtime conformance live.
- Guided tour: seven user stories from the command line, offline. Its runtime conformance finding is recorded. The same fleet opens in the terminal UI;
pacto tui --root oci://ghcr.io/trianalab/pacto/pacto-demo:1.0.0 --local ""opens most of it straight from the registry.
Available examples¶
| Service | Type | State | Description |
|---|---|---|---|
| PostgreSQL | service | stateful/persistent | Relational database |
| Redis | service | stateful/persistent | In-memory data store |
| RabbitMQ | service | stateful/persistent | Message broker |
| NGINX | service | stateless/ephemeral | Reverse proxy / web server |
| Cron Worker | scheduled | stateless/ephemeral | Scheduled batch job |
| Event Processor | service | stateless/ephemeral | Event-driven message consumer |
| gRPC Service | service | stateless/ephemeral | Microservice exposing a gRPC service descriptor |
| Hybrid Cache API | service | hybrid/persistent | API with local cache and upstream rebuild |
PostgreSQL¶
A stateful, persistent relational database with high data criticality.
pactoVersion: "2.0"
service:
name: postgresql
version: 16.4.0
owner:
team: databases
interfaces:
- name: metrics
type: openapi
ref: interfaces/metrics.yaml
visibility: internal
configurations:
- name: default
schema: configuration/schema.json
required: true
workload: service
state:
type: stateful
persistence:
scope: local
durability: persistent
dataCriticality: high
capabilities:
- type: health
binding:
type: http
interface: metrics
path: /health
- type: metrics
binding:
type: http
interface: metrics
path: /metrics
metadata:
tier: critical
backup: required
storage-class: ssd
Note
PostgreSQL's binary wire protocol and Redis's RESP below have no openapi, asyncapi or grpc spec, so neither contract declares them as interfaces. In both contracts the only declared interface is the HTTP endpoint the metrics exporter exposes, which the health and metrics capabilities bind to (see interface types).
state.type: statefulwithdurability: persistent: persistent storage survives pod restartsdataCriticality: high: backups and strict disruption budgets expected- Single instance: replication is handled externally; replica counts belong to the deployment
- Capabilities over ports: health and metrics are declared as capabilities bound to the exporter interface
Redis¶
A stateful in-memory data store with persistent durability.
pactoVersion: "2.0"
service:
name: redis
version: 7.4.0
owner:
team: caching
interfaces:
- name: metrics
type: openapi
ref: interfaces/metrics.yaml
visibility: internal
configurations:
- name: default
schema: configuration/schema.json
required: true
workload: service
state:
type: stateful
persistence:
scope: local
durability: persistent
dataCriticality: medium
capabilities:
- type: health
binding:
type: http
interface: metrics
path: /health
- type: metrics
binding:
type: http
interface: metrics
path: /metrics
metadata:
tier: high
eviction-policy: allkeys-lru
state.type: statefulwithdurability: persistent: Redis with AOF/RDB persistence enabled needs durable storagedataCriticality: medium: data is important but can be rebuilt from source if needed- Capabilities over ports: health and metrics are declared as capabilities bound to the exporter interface
For a pure cache without persistence:
RabbitMQ¶
A stateful message broker with persistent durability and multiple protocol interfaces.
pactoVersion: "2.0"
service:
name: rabbitmq
version: 3.13.7
owner:
team: messaging
interfaces:
- name: amqp
type: asyncapi
ref: interfaces/amqp.yaml
visibility: internal
- name: management
type: openapi
ref: interfaces/management-api.yaml
visibility: internal
- name: metrics
type: openapi
ref: interfaces/metrics.yaml
visibility: internal
configurations:
- name: default
schema: configuration/schema.json
required: true
workload: service
state:
type: stateful
persistence:
scope: local
durability: persistent
dataCriticality: high
capabilities:
- type: health
binding:
type: http
interface: management
path: /api/health/checks/alarms
- type: metrics
binding:
type: http
interface: metrics
path: /metrics
metadata:
tier: critical
cluster: required
quorum-queues: enabled
Note
RabbitMQ's AMQP is a message-oriented protocol, so the amqp interface uses type: asyncapi with an AsyncAPI document (see interface types). The management REST API is openapi, and the Prometheus metrics endpoint is a separate openapi interface the metrics capability binds to.
dataCriticality: high: message loss can cause data integrity issues across the systemstate.type: statefulwithdurability: persistent: queues and messages must survive restarts- Clustering is external: quorum-queue cluster sizing belongs to the deployment and is recorded in
metadata - Multiple interfaces: AsyncAPI for messaging, OpenAPI for the management API and metrics
NGINX¶
A stateless reverse proxy and web server.
pactoVersion: "2.0"
service:
name: nginx
version: 1.27.3
owner:
team: networking
interfaces:
- name: proxy
type: openapi
ref: interfaces/openapi.yaml
visibility: public
- name: metrics
type: openapi
ref: interfaces/metrics.yaml
visibility: internal
configurations:
- name: default
schema: configuration/schema.json
required: true
workload: service
state:
type: stateless
persistence:
scope: local
durability: ephemeral
dataCriticality: low
capabilities:
- type: health
binding:
type: http
interface: proxy
path: /health
- type: metrics
binding:
type: http
interface: metrics
path: /metrics
metadata:
tier: critical
edge: true
state.type: stateless: any instance can serve any requestdurability: ephemeral: no persistent storage neededvisibility: public: theproxyinterface is externally reachable; HTTP/HTTPS termination and ports belong to the deployment- Capabilities over ports: health and metrics are declared as capabilities bound to the declared interfaces
- No replica scaling: high availability and autoscaling belong to the deployment, and v2 has no
scalingsection
Cron Worker¶
A scheduled batch job: a stateless worker that runs on a cron schedule.
pactoVersion: "2.0"
service:
name: report-generator
version: 1.2.0
owner:
team: analytics
interfaces:
- name: health
type: openapi
ref: interfaces/health.yaml
visibility: internal
workload: scheduled
state:
type: stateless
persistence:
scope: local
durability: ephemeral
dataCriticality: low
capabilities:
- type: health
binding:
type: http
interface: health
path: /ready
metadata:
schedule: "0 2 * * *"
timeout: 3600
workload: scheduled: runs on a cron schedule- No replica scaling: batch workloads scale in the deployment, and v2 has no
scalingsection - Schedule in
metadata: the cron expression is platform-specific, so it lives inmetadata - Health as a capability: the readiness probe binds to the
healthinterface (see capabilities)
For a job that runs once (e.g., a database migration):
workload: job
state:
type: stateless
persistence:
scope: local
durability: ephemeral
dataCriticality: low
capabilities:
- type: health
binding:
type: http
interface: health
path: /ready
Event Processor¶
An event-driven service: a stateless consumer that processes messages from a message broker and exposes an HTTP health endpoint.
pactoVersion: "2.0"
service:
name: order-processor
version: 1.4.0
owner:
team: orders
interfaces:
- name: order-events
type: asyncapi
ref: interfaces/order-events.yaml
visibility: internal
- name: health
type: openapi
ref: interfaces/health.yaml
visibility: internal
configurations:
- name: default
required: true
schema: configuration/schema.json
values:
BROKER_HOST: rabbitmq.internal
BROKER_PORT: 5672
BROKER_CREDENTIALS: secret://vault/order-processor/broker-credentials
DEAD_LETTER_QUEUE: orders.dlq
MAX_RETRIES: 3
dependencies:
- name: rabbitmq
ref: oci://ghcr.io/acme/rabbitmq-pacto@sha256:0000000000000000000000000000000000000000000000000000000000000000
required: true
compatibility: "^3.13.0"
workload: service
state:
type: stateless
persistence:
scope: local
durability: ephemeral
dataCriticality: medium
capabilities:
- type: health
binding:
type: http
interface: health
path: /health
- type: metrics
binding:
type: http
interface: health
path: /metrics
metadata:
tier: standard
consumer-group: order-processing
type: asyncapi: declares an event-driven interface; the service consumes messages from a brokerref: interfaces/order-events.yaml: the AsyncAPI event schema is bundled and versioned with the servicedataCriticality: medium: event processing failures have moderate impact; dead-letter queues provide a safety net- Capabilities on the HTTP interface: health and metrics bind to the
healthOpenAPI interface (see capabilities) - Dependency target: the
rabbitmqdependency points to the RabbitMQ example, which publishes version3.13.7and satisfies the^3.13.0compatibility range - Secret reference: broker credentials use
secret://, an opaque convention the platform resolves at deployment time (see Secret references)
gRPC Service¶
A gRPC microservice: a user service exposing a gRPC API with internal visibility.
pactoVersion: "2.0"
service:
name: user-service
version: 3.2.0
owner:
team: identity
interfaces:
- name: grpc-api
type: grpc
ref: interfaces/user-service.yaml
visibility: internal
- name: metrics
type: openapi
ref: interfaces/metrics.yaml
visibility: internal
configurations:
- name: default
required: true
schema: configuration/schema.json
values:
DB_HOST: user-db.internal
DB_PORT: 5432
DB_PASSWORD: secret://vault/user-service/db-password
CACHE_TTL_SECONDS: 300
dependencies:
- name: postgres
ref: oci://ghcr.io/acme/postgres-pacto@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
required: true
compatibility: "^16.0.0"
workload: service
state:
type: stateless
persistence:
scope: local
durability: ephemeral
dataCriticality: low
capabilities:
- type: health
- type: metrics
binding:
type: http
interface: metrics
path: /metrics
metadata:
tier: critical
type: grpc: the gRPC service descriptor is bundled in the OCI artifact, so the API contract travels with the service version. Thereffile must parse as JSON or YAML (see interface types)- Health as a capability with no binding: a
healthcapability without an HTTP binding declares that the service implements the gRPC Health Checking Protocol (see capabilities) - Metrics over HTTP: the gRPC interface serves application traffic while the
metricscapability binds to a separate HTTP interface exposing Prometheus metrics stateless: the service itself holds no state; data lives in PostgreSQL (thepostgresdependency resolves to the PostgreSQL example)
Hybrid Cache API¶
A service with hybrid state: an API that caches data locally for performance and can rebuild its cache from an upstream source. Losing local state slows the service down until the cache warms up again.
pactoVersion: "2.0"
service:
name: product-catalog
version: 2.0.1
owner:
team: catalog
interfaces:
- name: rest-api
type: openapi
ref: interfaces/openapi.yaml
visibility: public
- name: metrics
type: openapi
ref: interfaces/metrics.yaml
visibility: internal
configurations:
- name: default
required: true
schema: configuration/schema.json
values:
UPSTREAM_API: https://inventory.internal/api
CACHE_MAX_SIZE_MB: 512
CACHE_TTL_SECONDS: 3600
WARMUP_ON_START: true
API_KEY: secret://vault/product-catalog/upstream-api-key
dependencies:
- name: inventory
ref: oci://ghcr.io/acme/inventory-pacto@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
required: true
compatibility: "^1.0.0"
workload: service
state:
type: hybrid
persistence:
scope: local
durability: persistent
dataCriticality: low
capabilities:
- type: health
binding:
type: http
interface: rest-api
path: /health
- type: metrics
binding:
type: http
interface: metrics
path: /metrics
metadata:
tier: standard
cache-strategy: write-through
state.type: hybrid: the service caches product data locally for fast reads, but can reconstruct the cache from the upstream inventory service on restartdurability: persistent: persisting the cache across restarts avoids cold-start latency, and without it the service warms up firstdataCriticality: low: the cache is reconstructible; losing it has no business impact beyond temporary performance degradation- Capabilities over ports: health binds to the public
rest-apiinterface and metrics to a separate internal interface (see capabilities) - Secret reference: the API key for the upstream service uses
secret://so the contract holds a reference to the credential
When to use hybrid¶
Choose hybrid over stateless when local state persists across restarts to avoid warm-up but the service still functions after losing it; a purely in-memory cache rebuilt on every start is stateless/ephemeral. The state.type table has the full breakdown.
Using examples as dependencies¶
You can reference these contracts (once published to a registry) as dependencies in your own pacto.yaml:
dependencies:
- name: postgres
ref: oci://ghcr.io/acme/postgres-pacto@sha256:abc1230000000000000000000000000000000000000000000000000000000000
required: true
compatibility: "^16.0.0"
- name: redis
ref: oci://ghcr.io/acme/redis-pacto@sha256:def4560000000000000000000000000000000000000000000000000000000000
required: false
compatibility: "^7.0.0"
The ghcr.io/acme/… refs above are placeholders. The one Pacto contract anyone can pull is the dashboard's own, and pacto explain prints it:
See the contract reference for the full dependency schema.
Then run pacto graph from the bundle directory to see the resolved tree:
It prints the service and one line per dependency. A ref it cannot resolve, such as the placeholders above, becomes an error node in the tree, and the command still exits 0.
One contract, many sections¶
This contract declares most optional sections at once. Use it as a field
checklist. Only pactoVersion and service are required. The three sections
it leaves out, readiness, metadata and extensions, are in
Contract sections, which is the complete list.
pactoVersion: "2.0"
service:
name: payments-api
version: 2.1.0
owner:
team: payments
dri: alice
interfaces:
- name: rest-api
type: openapi
ref: interfaces/openapi.yaml
visibility: public
capabilities:
- type: health
binding:
type: http
interface: rest-api
path: /health
- type: metrics
binding:
type: http
interface: rest-api
path: /metrics
configurations:
- name: default
schema: configuration/schema.json
required: true
policies:
- name: platform-policy
schema: policy/schema.json
dependencies:
- name: auth
ref: oci://ghcr.io/acme/auth-pacto:2.0.0
required: true
compatibility: "^2.0.0"
workload: service
state:
type: stateful
persistence:
scope: shared
durability: persistent
dataCriticality: high
Writing a contract like this is the first step. Next, tools read it:
pacto explain and MCP for people and AI assistants.
Then, on Kubernetes, the operator
checks the running service against it. The model
shows the whole loop.