Skip to main content

Pact Broker vs PactFlow for Small Teams

When you move beyond sharing pact files on a shared drive and need reliable can-i-deploy gates in CI, you have to pick a broker. The choice is between running the open-source Pact Broker yourself and paying for the managed PactFlow SaaS. This guide is part of Consumer-Driven Contracts with Pact and is aimed at small engineering teams — typically 2–10 engineers, 3–15 services — deciding which path to take.

The short version: the open-source broker is production-ready and free, but you own the infrastructure. PactFlow removes all operational overhead and unlocks bi-directional contract testing and enterprise features, at a monthly cost. The decision turns on three variables: how much CI reliability you can afford to trade for ops savings, whether you need bi-directional contracts, and what your monthly SaaS budget looks like.

Pact Broker vs PactFlow for small teams Two columns comparing self-hosted Pact Broker (left, amber) and managed PactFlow (right, copper). Each column lists the key characteristics: hosting model, cost, notable features, and ops burden. Self-Hosted Pact Broker

Hosting Your Docker / k8s / Fly.io instance

Cost $0 license + infra cost (~$5–20/mo)

Core features can-i-deploy, webhooks, HAL browser Version matrix, environment tracking

Missing Bi-directional contracts, secrets, SSO, RBAC, managed SLA

Ops burden You manage upgrades, DB, backups

Managed PactFlow

Hosting SmartBear-managed SaaS (99.9% SLA)

Cost Free (Starter, ≤5 users) or ~$300/mo+

Core features All open-source features, plus: Bi-directional contracts, webhook secrets SSO (SAML/OIDC), RBAC, audit log

Missing Self-host option (SaaS only), on-prem deployment

Ops burden Zero — SmartBear handles everything

When Each Fits

Use the self-hosted Pact Broker when

  • Your team is already comfortable running Docker-based infrastructure (a Postgres-backed container is all you need).
  • You operate in a regulated environment that prohibits sending contract data to a third-party SaaS — on-prem or VPC-isolated deployments are straightforward.
  • Your budget for tooling SaaS is near zero and you can absorb a few hours per quarter of maintenance.
  • Your integration surface is HTTP consumer-driven contracts only — you do not need bi-directional testing of existing OpenAPI specs against real provider responses.
  • The team is small enough that a single shared broker token is acceptable; you do not need per-team RBAC or SSO.

Use PactFlow when

  • You want zero operational overhead: no Docker to maintain, no Postgres to back up, no upgrade windows to plan.
  • Your team needs bi-directional contract testing — uploading an OpenAPI spec as a provider-side contract and having PactFlow compare it against consumer pact files without writing a provider verification test. This is the single largest capability gap between the two options; see Bi-Directional Contract Testing Explained for the mechanics.
  • Webhooks need to carry credentials (API keys, JWT tokens) for private CI systems. PactFlow stores webhook secrets encrypted; the open-source broker stores them in plaintext in the database.
  • Your organization’s security policy requires SSO — the open-source broker has no SAML/OIDC support.
  • You have more than five engineers contributing pacts and need separate access tokens per team or read-only tokens for downstream consumers.
  • You are already paying for SmartBear tooling (ReadyAPI, SwaggerHub) and PactFlow licensing is bundled or discounted.

Feature Comparison

Feature Pact Broker (OSS) PactFlow Starter PactFlow Team
Hosting Self-managed Docker / k8s Managed SaaS Managed SaaS
Maintenance You own upgrades and DB None None
can-i-deploy Yes Yes Yes
Webhooks Yes (no secret storage) Yes + encrypted secrets Yes + encrypted secrets
Bi-directional contracts No Yes Yes
HAL browser / UI Yes Yes (enhanced) Yes (enhanced)
Environment tracking Yes Yes Yes
SSO (SAML / OIDC) No No Yes
Role-based access control No No Yes
Audit log No No Yes
Support SLA Community forum Email support Priority support
Users Unlimited Up to 5 Up to 20
Teams / namespaces No 2 Unlimited
Price Infra cost only $0 ~$300/mo (check pactflow.io)

Self-Hosted Pact Broker: Annotated docker-compose

A production-ready self-hosted broker needs only two containers: Postgres and the broker itself. The configuration below is suitable for a small team running on a VPS, Fly.io, or an internal k8s cluster.

# docker-compose.yml — Pact Broker 2.x + Postgres 15
# Run with: docker compose up -d
version: "3.9"

services:
  postgres:
    image: postgres:15-alpine
    restart: unless-stopped
    environment:
      POSTGRES_USER: pact          # broker DB user
      POSTGRES_PASSWORD: "${DB_PASSWORD}"  # set in .env or CI secret
      POSTGRES_DB: pact
    volumes:
      - pact_postgres_data:/var/lib/postgresql/data  # persist across restarts
    healthcheck:
      test: ["CMD", "pg_isready", "-U", "pact"]
      interval: 10s
      retries: 5

  broker:
    image: pactfoundation/pact-broker:2.x.x  # pin a specific release tag
    restart: unless-stopped
    depends_on:
      postgres:
        condition: service_healthy  # wait for Postgres to accept connections
    ports:
      - "9292:9292"               # expose the broker UI and API
    environment:
      PACT_BROKER_DATABASE_URL: "postgres://pact:${DB_PASSWORD}@postgres/pact"
      PACT_BROKER_BASIC_AUTH_USERNAME: "${BROKER_USER}"    # read/write UI login
      PACT_BROKER_BASIC_AUTH_PASSWORD: "${BROKER_PASSWORD}"
      PACT_BROKER_ALLOW_PUBLIC_READ: "false"               # lock down the API
      PACT_BROKER_BASE_URL: "https://pact.internal.example.com"  # canonical URL for links
      PACT_BROKER_LOG_LEVEL: "info"
      # Optional: auto-delete pact versions older than 90 days to keep DB lean
      PACT_BROKER_DELETE_PACTICIPANT_VERSION_CONTENT_AFTER_DAYS: "90"

volumes:
  pact_postgres_data:

Environment file (.env — never commit this):

DB_PASSWORD=a-strong-random-password
BROKER_USER=admin
BROKER_PASSWORD=another-strong-password

Put the broker behind a TLS-terminating reverse proxy (nginx, Caddy, or a cloud load balancer). Point PACT_BROKER_BASE_URL at the public HTTPS address — the broker embeds this in webhook payloads and HAL links, and an HTTP address here causes webhook delivery to insecure endpoints.

Publishing Pacts: Broker vs PactFlow Side-by-Side

The pact-broker publish command is identical for both targets. The only differences are the URL and the token format.

Publishing to the self-hosted broker

# Uses HTTP basic auth via the token format "user:password" encoded in PACT_BROKER_TOKEN,
# or pass --broker-username / --broker-password explicitly.
npx pact-broker publish ./pacts \
  --consumer-app-version "$GITHUB_SHA" \
  --branch "$GITHUB_REF_NAME" \
  --broker-base-url "https://pact.internal.example.com" \
  --broker-username "$BROKER_USER" \
  --broker-password "$BROKER_PASSWORD"

Publishing to PactFlow

# PactFlow issues a bearer token (PACT_BROKER_TOKEN) from Settings → API Tokens.
# The --broker-token flag sends it as Authorization: Bearer <token>.
npx pact-broker publish ./pacts \
  --consumer-app-version "$GITHUB_SHA" \
  --branch "$GITHUB_REF_NAME" \
  --broker-base-url "https://your-team.pactflow.io" \
  --broker-token "$PACT_BROKER_TOKEN"

Migrating from self-hosted to PactFlow

Switching targets is a one-line CI environment variable change: replace PACT_BROKER_BASE_URL and swap --broker-username/--broker-password for --broker-token. No application code changes, no pact file format changes. Historical verification results are not migrated, but all new publish and verify calls start populating the PactFlow matrix immediately.

# GitHub Actions: set these as repository secrets, then use them in every job
# Old:
#   PACT_BROKER_URL: https://pact.internal.example.com
#   PACT_BROKER_USER: admin
#   PACT_BROKER_PASS: ...
# New:
#   PACT_BROKER_URL: https://your-team.pactflow.io
#   PACT_BROKER_TOKEN: <bearer-token-from-pactflow-settings>

Gating deployments with can-i-deploy (identical syntax on both)

npx pact-broker can-i-deploy \
  --pacticipant "user-api" \
  --version "$GITHUB_SHA" \
  --to-environment production \
  --broker-base-url "$PACT_BROKER_URL" \
  --broker-token "$PACT_BROKER_TOKEN" \
  --retry-while-unknown 12 \
  --retry-interval 10

The can-i-deploy command is part of the open-source pact-broker CLI and works against either backend. The broker token flag accepts basic-auth credentials formatted as username:password for the self-hosted broker when you have not configured a bearer token.

Recommendation for Small Teams

For a team of two to ten engineers with fewer than fifteen services, the decision tree is straightforward:

Start with PactFlow Starter (free tier) unless you have a regulatory or budget blocker. The Starter plan covers five users and two team namespaces — enough for most small teams. You get managed infrastructure, encrypted webhook secrets, and the bi-directional contract testing feature from day one. The total cost is zero until you exceed the user limit, at which point you either upgrade to the Team plan or migrate to self-hosted.

Self-host if: your organization prohibits sending contract data to a third-party SaaS, you are already running a container platform that makes the ops overhead negligible, or your team has grown past PactFlow Starter limits and the Team plan’s cost is not justified by the bi-directional feature or SSO requirement.

Do not self-host if: your team lacks anyone comfortable operating a Postgres-backed Docker service in production, you need webhook secrets, or you plan to adopt bi-directional contract testing to validate existing OpenAPI specs against consumer pact files.

The practical sequence for a new team: start on PactFlow Starter, get can-i-deploy gates working across all services, and then decide at the five-user boundary whether to upgrade or migrate. The migration is low risk because the CLI interface is identical.

For the full end-to-end workflow — consumer tests, provider states, and CI integration — see verifying provider contracts in CI with Pact.

Verification

Once your broker is running (self-hosted or PactFlow), validate the connection before wiring up CI:

# Confirm the broker responds and basic auth / token is accepted
curl -u "$BROKER_USER:$BROKER_PASSWORD" https://pact.internal.example.com/diagnostic/status
# Expected: {"status":"ok","version":"2.x.x","branch":"..."}

# For PactFlow with bearer token:
curl -H "Authorization: Bearer $PACT_BROKER_TOKEN" https://your-team.pactflow.io/diagnostic/status

# List all registered pacticipants (empty on a fresh install)
npx pact-broker list-latest-pact-versions \
  --broker-base-url "$PACT_BROKER_URL" \
  --broker-token "$PACT_BROKER_TOKEN"

A healthy self-hosted broker also serves the HAL browser at / — opening that URL in a browser and seeing the navigation links confirms the application and Postgres connection are working correctly.

After your first publish-and-verify cycle, inspect the matrix:

npx pact-broker can-i-deploy \
  --pacticipant "web-frontend" \
  --version "$GITHUB_SHA" \
  --to-environment production \
  --broker-base-url "$PACT_BROKER_URL" \
  --broker-token "$PACT_BROKER_TOKEN" \
  --output table

The --output table flag prints each participant row and its verification status, making it easy to spot missing verifications in a new setup.

Edge Cases and Caveats

  • Database backup is entirely your responsibility on the self-hosted broker. The broker stores the full pact and verification history in Postgres. A lost database means your can-i-deploy matrix is empty — all gates will block until every provider re-publishes verification results. Schedule daily pg_dump exports and test restoration periodically.
  • PactFlow Starter does not support SSO or per-team tokens. If your organization’s security policy requires SSO, you must upgrade to the PactFlow Team plan; there is no SSO option on the open-source broker at all. Do not work around this by sharing a single token across teams — rotate tokens per service using the PactFlow API tokens page or broker basic-auth accounts.
  • Webhook secret storage differs materially. The self-hosted broker stores webhook request headers (including Authorization values) in plaintext in Postgres. Anyone with database access can read CI tokens. If your webhooks call private CI endpoints with credentials, either use PactFlow (which encrypts secrets), use a short-lived token rotated by a secrets manager, or proxy webhook calls through a system that injects credentials at delivery time.

Frequently Asked Questions

Can a small team run the Pact Broker for free indefinitely?

Yes. The open-source Pact Broker is MIT-licensed and free to self-host on any container platform. The only costs are the compute and storage you provision, and the engineer time required to maintain it.

What does PactFlow add that the open-source Pact Broker does not have?

PactFlow adds bi-directional contract testing (provider-side OpenAPI or Postman collection upload), secret management for webhooks, team-scoped access tokens, SSO via SAML/OIDC, role-based access control, and a managed SLA. None of these exist in the open-source broker.

How much does PactFlow cost for a small team?

PactFlow’s Starter plan is free for up to 5 users and 2 teams. The Team plan starts at around $300 per month and supports up to 20 users. Enterprise pricing is negotiated separately. Check pactflow.io for current pricing as it changes.

Does can-i-deploy work with the self-hosted Pact Broker?

Yes. can-i-deploy is a core feature of the open-source broker, not a PactFlow exclusive. Both implementations support the same CLI flags and environment selectors.

Can I migrate from the self-hosted Pact Broker to PactFlow later?

Yes. The wire format is identical. You update PACT_BROKER_URL and PACT_BROKER_TOKEN in your CI environment and existing pact-broker CLI commands work without code changes. Historical contract data is not migrated automatically, but new publishes pick up immediately.

Does PactFlow support bi-directional contract testing for gRPC or GraphQL?

PactFlow’s bi-directional feature currently supports OpenAPI specs and Postman collections as provider-side contracts. gRPC (Protocol Buffers) and GraphQL SDL uploads are not natively supported as of mid-2026; those protocols are handled through Pact’s standard consumer-driven flow.