Documentation

Everything you need to build and operate a federated GraphQL API with feddi.

Agent-first platform

feddi is designed to be operated primarily through the feddi CLI. Every action is a CLI command: creating graphs, publishing schemas, managing keys, checking composition. This makes feddi a natural fit for AI coding agents like Claude Code, Cursor, or Copilot that can drive the entire workflow programmatically.

Overview

A tour of how feddi is put together: the two components that make up the system, how graphs and variants model your federated API, and how organizations group it all together.

Architecture

feddi has two components: the feddi Gateway that you self-host in your infrastructure, and the feddi Platform hosted at feddi.dev that manages schemas, composition, and analytics.

feddi architecture: gateway (self-hosted) connects to your subgraphs and the feddi Platform

The feddi Gateway runs in your infrastructure alongside your subgraph services. It receives GraphQL requests from clients (web, mobile, AI agents), plans query execution across subgraphs, and returns unified responses. It polls the feddi Platform for schema updates and reports usage analytics.

The feddi Platform (feddi.dev) stores your subgraph schemas, composes them into a supergraph, detects breaking changes, tracks field-level usage, and serves persisted documents. You interact with it through the feddi CLI.

This separation means your data never passes through the feddi Platform: all GraphQL traffic stays within your infrastructure. The feddi Platform only handles metadata: schemas, analytics, and configuration.

Graphs & variants

A graph represents a federated GraphQL API. Each graph belongs to an organization and contains one or more variants.

Variants are independent environments of the same graph (e.g., production, staging, development). Each variant has its own set of subgraphs, composed supergraph, API keys, and usage analytics.

This lets you test schema changes in staging before promoting to production, with fully isolated composition and gateway configuration per variant.

Organization hierarchy: Org → Members + Graphs → Variants → Subgraphs → Supergraph

Users and organizations

An organization groups graphs, members, keys, and billing. A user is a single account identified by email.

Users and organizations are a many-to-many relationship: a user can belong to several organizations at once (each with its own role), and an organization has many members. Graphs, subgraphs, keys, and persisted-document lists are all owned by the organization, not the user: switching organizations changes what you can see and manage.

Signing up creates an organization

When you sign up via /platform/signup without an invitation, feddi creates a new organization and makes you its Owner. If you were instead invited to an existing org, accepting the invitation joins you to that org with the role the inviter chose, and no new organization is created in that case. A user can repeat either flow to end up in multiple organizations.

Roles

Role is set per-membership, so the same user can be Owner in one org and Member in another.

Owner: Full control including org deletion and ownership transfer.
Admin: Can invite/remove members, manage graphs, create keys.
Member: Basic read access and schema publishing.

Member limits

The Free tier supports up to 10 members per organization (including pending invitations). Upgrade to Enterprise for unlimited members.

Invitations

Owners and Admins can invite Members by email. Invitations expire after 7 days and can be resent or revoked. Invited users who don't yet have a feddi account go through a one-click accept flow that creates the account and the membership in a single step.

GraphQL Federation spec

feddi implements the open GraphQL Federation (Composite Schemas) specification maintained under the GraphQL Foundation. Subgraph schemas use the standard federation directives (@lookup, @external, @requires, @provides, @shareable, etc.) and the platform composes them into a supergraph following the spec's rules.

Because the wire format and subgraph contract are standard, feddi interoperates with any GraphQL server framework. You aren't locked into a feddi-specific runtime on the subgraph side.

Getting Started

feddi lets you compose multiple GraphQL services into a single, unified API. Each service (subgraph) owns its slice of the schema, and feddi composes them into a supergraph.

1. Sign up and create an organization

Create an account at feddi.dev/platform/signup. Each account belongs to an organization where you manage graphs, members, and API keys.

2. Install the feddi CLI

Download the feddi CLI from the Downloads page, then authenticate:

feddi auth login --token <your-personal-access-token>

3. Create a graph and variant

feddi graph create <org-id> "My Graph"
feddi variant create <graph-id> "production"

4. Create and publish a subgraph

feddi subgraph create <variant-id> "users"
feddi subgraph publish <subgraph-id> --schema ./users.graphqls --config '{"url":"https://users.example.com/graphql"}'

feddi composes your subgraph schemas into a supergraph automatically and validates compatibility.

5. Start the feddi Gateway

Download the feddi Gateway binary from the Downloads page, create a feddi-gateway.yml with your graph variant key, and start it. The feddi Gateway polls the feddi Platform for schema updates.

feddi Gateway

The feddi Gateway is a standalone Java application that receives GraphQL requests from clients, plans query execution across your subgraphs, and returns unified responses.

It is an open-source project (Apache License 2.0) hosted at github.com/feddi-dev/feddi-gateway. The feddi Gateway works best alongside the feddi Platform (for schema polling, usage reporting, persisted-document resolution, and managed credentials), but does not depend on it: you can run the feddi Gateway with a locally-supplied supergraph SDL and no platform connection at all. See the gateway README for the standalone usage modes.

Get started

Download a prebuilt feddi Gateway distribution bundled with the feddi-platform extension from the Downloads page. The archive contains the feddi Gateway JAR, launcher scripts for Linux, macOS, and Windows, and a sample feddi-gateway.yml that you can edit in place to point at your graph variant key.

Configuration reference

All runtime configuration lives in a single feddi-gateway.yml in the working directory. A minimal platform-connected example:

port: 8080
enable-introspection: false
max-request-size-bytes: 2097152
logging:
  dir: ./logs
extensions:
  feddi:
    api-url: https://feddi.dev
    graph-variant-key: fddi_gvk_your_key_here
    poll-interval-seconds: 600

Core gateway options (top-level keys)

port

Integer, default 8080. HTTP port for the public GraphQL endpoint (/graphql).

enable-introspection

Boolean, default true. Set to false in production to prevent schema discovery via standard GraphQL introspection.

management-port

Integer, default 9090. Port for Spring Boot actuator endpoints: /actuator/health, /actuator/info, /actuator/prometheus.

management-address

String, default 127.0.0.1. Bind address for the management server. Set to 0.0.0.0 for Docker / Kubernetes liveness and readiness probes.

max-request-size-bytes

Long, default 2097152 (2 MB). Incoming requests above this size are rejected with HTTP 413. Set to 0 to disable the limit.

logging.dir

String, default . (current working directory). Directory for the rolling feddi-gateway.log file: daily rotation, 100 MB per file, 30-day retention, 1 GB total cap.

extensions

Map, default empty. Namespace-keyed config forwarded to loaded extensions. Each installed extension picks up its own subtree (e.g. the feddi Platform extension reads extensions.feddi.*). The mere presence of a namespace here is what activates the extension's auto-configuration.

Platform extension (extensions.feddi.*)

Only active when the feddi-platform-extensions JAR is present in libs/ (the prebuilt distribution includes it).

extensions.feddi.api-url

String, required in platform mode. Base URL of the feddi Platform API, e.g. https://feddi.dev.

extensions.feddi.graph-variant-key

String, required in platform mode. Bearer token (fddi_gvk_…) that identifies the variant for schema polling and scopes usage reports.

extensions.feddi.poll-interval-seconds

Long, default 600 (10 min). How often the feddi Gateway polls the feddi Platform for supergraph updates.

extensions.feddi.usage-report-interval-seconds

Long, default 10. How often buffered per-request usage data is flushed to the feddi Platform.

extensions.feddi.usage-report-batch-size

Integer, default 1000. Maximum number of usage records sent per flush batch.

extensions.feddi.persisted-documents-poll-interval-seconds

Long, default 60. How often the feddi Gateway polls for new or updated persisted documents attached to the variant.

Launcher environment variables

Consumed by the bin/feddi-gateway launcher script in the prebuilt distribution. They do not affect java -jar feddi-gateway.jar invoked directly.

FEDDI_GATEWAY_JAVA_HOME

Path to a Java 25+ installation used specifically for the feddi Gateway. Takes precedence over JAVA_HOME.

JAVA_HOME

Fallback Java installation when FEDDI_GATEWAY_JAVA_HOME is not set. Must point at Java 25 or newer.

JAVA_OPTS

Extra JVM flags appended after the launcher's defaults (-XX:+UseZGC -Xms256m -Xmx1g -XX:SoftMaxHeapSize=768m -XX:+UseStringDeduplication -XX:+AlwaysPreTouch, plus OOM handling). Use this to bump memory, e.g. JAVA_OPTS="-Xmx2g".

Subgraphs

A subgraph is a named GraphQL service in a variant. Creating a subgraph only creates that identity; it does not publish a schema or configure a gateway endpoint.

The subgraph config is JSON that is published alongside the schema SDL. Today the gateway reads the url field to decide where to send requests for that subgraph. The gateway always reads the SDL and config from the latest successful publish event, not from an independently editable subgraph setting.

Publishing schemas

The first publish attempt for a subgraph must include valid JSON config. feddi composes the submitted SDL with the latest successful SDL and config from the other subgraphs in the variant. If composition succeeds, the new supergraph and the submitted SDL/config snapshot become visible to the feddi Gateway on its next poll.

feddi subgraph create <variant-id> users
feddi subgraph publish <subgraph-id> --schema ./schema.graphqls --config '{"url":"https://users.example.com/graphql"}'

After a subgraph has a successful publish, later schema-only publishes can omit --config. In that case feddi reuses the config from the latest successful publish for that subgraph.

feddi subgraph publish <subgraph-id> --schema ./schema.graphqls

Updating subgraph config

To change where the gateway routes a subgraph, publish again with --config. If the SDL is unchanged, pass the same schema file with the new config. A failed publish does not replace the gateway-visible SDL or config; the gateway continues using the latest successful publish.

feddi subgraph publish <subgraph-id> --schema ./schema.graphqls --config '{"url":"https://users-v2.example.com/graphql"}'

Schema checks

Before publishing, you can run a schema check to verify composition and detect breaking changes without persisting anything. Checks can use an explicit config, or omit it after the subgraph already has a successful publish.

feddi subgraph check <subgraph-id> --schema ./schema.graphqls --config '{"url":"https://users.example.com/graphql"}'
feddi subgraph check <subgraph-id> --schema ./schema.graphqls

Breaking change detection

Both publish and check detect breaking changes by comparing the old and new supergraph schemas. Breaking changes (field removals, type changes, nullability changes) are rejected by default.

Override flags

Two mutually exclusive flags allow overriding:

--allow-breaking-changes

Force-accept all breaking changes regardless of usage.

--allow-breaking-changes-if-not-used

Accept breaking changes only if the affected fields have no usage in the last 30 days. Fields with recent traffic will still be rejected.

Persisted Documents

Persisted document lists (PDLs) let you pre-register GraphQL operations so clients can send a hash instead of the full query string. This reduces payload size and enables safelisting.

feddi pdl create <graph-id> "my-pdl"
feddi pdl link <variant-id> <pdl-id>

Publish documents

feddi pdl publish <pdl-id> --document ./query.graphql

The SHA-256 hash is computed server-side. Publishing is idempotent: duplicate documents are ignored.

Publishing from CI

A CLI session authenticated as an Admin or Owner (via personal access token) can publish documents, but in practice you don't want your frontend-build pipeline holding Admin credentials. For that, create a persisted-document publish key: a graph-scoped credential that is allowed to publish documents to any PDL on its graph and nothing else. It cannot create/link/delete PDLs, publish subgraphs, or read schemas.

Typical flow, run once by an Owner or Admin:

feddi pd-publish-key create <graph-id> "frontend-ci" --expires 2026-12-31T00:00:00Z

The command prints a token prefixed with fddi_pdpk_. Store it as a secret in your CI (GitHub Actions secret, etc.), then in the build job:

feddi auth login --token "$FEDDI_PDPK"
feddi pdl publish <pdl-id> --document ./persisted-documents.graphql

Rotate by issuing a new key and feddi pd-publish-key revoke <old-key-id>.

Wire protocol

The feddi Gateway supports the Apollo APQ protocol by default. Clients send extensions.persistedQuery.sha256Hash instead of a query string. The protocol is customizable via the PersistedDocumentProtocol extension point.

Usage & Analytics

The feddi Gateway reports field-level usage data to the feddi Platform. This data powers analytics dashboards, breaking change detection, and monthly usage limits.

What's tracked

Per operation: name, type (query/mutation), hash, field coordinates, client name/version, duration, errors. Data is aggregated into hourly buckets and retained for 30 days.

Monthly limits (Free tier)

Each variant has a monthly limit of 1,000,000 requests and 250,000 usage buckets. When limits are reached, the feddi Gateway continues serving requests but stops reporting usage data. Upgrade to Enterprise for unlimited operations.

CLI commands

feddi usage list <variant-id>

List field usage with request counts, error counts, and client breakdown.

feddi usage field <variant-id> <field-coordinate>

Show usage detail for a specific field (e.g., Query.user).

Keys & Authentication

Personal access tokens

PATs authenticate your CLI and API requests as your user account. Create them in Settings → Access Tokens.

Graph variant keys

Graph variant keys authenticate the feddi Gateway. They're scoped to a variant and grant access to all subgraphs within it. The feddi Gateway uses the graph variant key to poll for schema updates and report usage.

feddi graph-variant-key create <variant-id> "gateway-key" --expires 2026-12-31T00:00:00Z

Subgraph keys

Subgraph keys are scoped to specific subgraphs within a variant. Use them in CI/CD pipelines for publishing schemas with least-privilege access.

feddi subgraph-key create <variant-id> "ci-key" --subgraphs <id1>,<id2> --expires 2026-12-31T00:00:00Z

Persisted-document publish keys

Graph-scoped keys that authorize one thing: publishing documents to any PDL belonging to the target graph. They cannot create, link, or delete PDLs, publish subgraphs, or read schemas, and are designed for frontend-build CI pipelines that need to ship a persisted-query manifest on every deploy without exposing broader privileges.

feddi pd-publish-key create <graph-id> "ci-key" --expires 2026-12-31T00:00:00Z

CLI Reference

Complete command reference. All commands support --json for machine-readable output.

Automatic updates

The feddi CLI checks /releases/latest/manifest.json once a day at startup and silently upgrades itself when a newer build is available. The check fetches a small JSON (a few hundred bytes), verifies the new tarball's SHA-256 against the manifest before any filesystem write, and swaps the binary atomically. A one-line confirmation is printed to stderr after a successful update. A failed check (network timeout, checksum mismatch, missing write permission) never aborts the command you ran.

The check is automatically skipped in environments where an update would be disruptive: when CI=true, when stdout is not a terminal (piped/scripted output), and when the feddi CLI is a source build (feddi version reports dev).

To opt out explicitly:

--no-update

Flag on any command; skips the update check for that one invocation.

FEDDI_DISABLE_AUTO_UPDATE=1

Environment variable; persists across all invocations for that shell.

feddi update

Force an immediate check, bypassing the 24-hour cache and the CI/TTY skip heuristics. Use this when you want to pull the latest build right now (e.g. after a known release) without waiting for the next day's automatic check.

Set FEDDI_DEBUG=1 to see why a check was skipped or why one failed.

Authentication

feddi auth login

Save a personal access token. Interactive by default; pass --token to skip the prompt.

Flags: --token <token>

Who: no auth required

feddi whoami

Show the currently authenticated user.

Who: any signed-in user

Graphs

feddi graph list <org-id>

List graphs in an organization.

Who: Member Admin Owner

feddi graph create <org-id> <name>

Create a graph.

Who: Admin Owner

feddi graph view <graph-id>

View graph details.

Who: Member Admin Owner

feddi graph update <graph-id> --name <new-name>

Rename a graph.

Who: Admin Owner

feddi graph delete <graph-id>

Delete a graph and all its variants.

Who: Admin Owner

Variants

feddi variant create <graph-id> <name>

Create a variant.

Flags: --endpoint <url>

Who: Admin Owner

feddi variant list <graph-id>

List variants of a graph.

Who: Member Admin Owner

feddi variant update <variant-id>

Update a variant's name or supergraph endpoint URL. At least one flag must be provided.

Flags: --name <name> · --endpoint <url>

Who: Admin Owner

feddi variant delete <variant-id>

Delete a variant.

Who: Admin Owner

Subgraphs

feddi subgraph create <variant-id> <name>

Create a named subgraph identity. Config is supplied when publishing, not at create time.

Who: Admin Owner

feddi subgraph publish <subgraph-id> --schema <file> [--config <json>]

Publish schema and endpoint configuration. First publish requires config; later publishes reuse the latest successful config when omitted. To update config, publish again with the current schema and new config.

Flags: --config · --allow-breaking-changes · --allow-breaking-changes-if-not-used

Who: Admin Owner subgraph key graph variant key

feddi subgraph check <subgraph-id> --schema <file> [--config <json>]

Check composition and breaking changes without persisting. Config is required when the subgraph has no successful publish yet; otherwise the latest successful config is reused when omitted.

Flags: --config · --allow-breaking-changes · --allow-breaking-changes-if-not-used

Who: Admin Owner subgraph key graph variant key

feddi subgraph sdl <subgraph-id>

Output the latest successfully published SDL to stdout.

Who: Member Admin Owner

feddi subgraph list <graph-id>

List subgraphs. The config column shows the latest successful publish config when available.

Who: Member Admin Owner

feddi subgraph delete <subgraph-id>

Delete a subgraph.

Who: Admin Owner

Persisted document lists

feddi pdl create <graph-id> <name>

Create a persisted document list.

Who: Admin Owner

feddi pdl list <graph-id>

List persisted document lists.

Who: Member Admin Owner

feddi pdl link <variant-id> <pdl-id>

Link a PDL to a variant.

Who: Admin Owner

feddi pdl unlink <variant-id>

Unlink the PDL from a variant.

Who: Admin Owner

feddi pdl publish <pdl-id> --document <file>

Publish a document to the list.

Flags: --client-name <name>

Who: Admin Owner pd publish key

feddi pdl documents <pdl-id>

List documents in a PDL.

Who: Member Admin Owner

feddi pdl delete <pdl-id>

Delete a persisted document list.

Who: Admin Owner

Keys

feddi graph-variant-key create <variant-id> <name> --expires <timestamp>

Create a graph variant key for gateway authentication.

Who: Admin Owner

feddi graph-variant-key list <graph-id>

List graph variant keys. Members can run this but get an empty list: key fields are hidden from them.

Who: Admin Owner

feddi graph-variant-key revoke <key-id>

Revoke a graph variant key.

Who: Admin Owner

feddi subgraph-key create <variant-id> <name> --subgraphs <ids> --expires <timestamp>

Create a subgraph key scoped to specific subgraphs.

Who: Admin Owner

feddi subgraph-key list <graph-id>

List subgraph keys. Members can run this but get an empty list: key fields are hidden from them.

Who: Admin Owner

feddi subgraph-key revoke <key-id>

Revoke a subgraph key.

Who: Admin Owner

feddi pd-publish-key create <graph-id> <name> --expires <timestamp>

Create a graph-scoped persisted-document publish key. Authorizes publishing documents to any PDL on the target graph and nothing else.

Who: Admin Owner

feddi pd-publish-key list <graph-id>

List PD publish keys for a graph. Members can run this but get an empty list: key fields are hidden from them.

Who: Admin Owner

feddi pd-publish-key revoke <key-id>

Revoke a PD publish key.

Who: Admin Owner

Usage analytics

feddi usage list <variant-id>

List field usage with request counts and client breakdown.

Who: Member Admin Owner

feddi usage field <variant-id> <field-coordinate>

Show usage detail for a specific field.

Who: Member Admin Owner

feddi usage last-used <variant-id> <field-coordinate>

Show when a field was last used.

Who: Member Admin Owner

feddi usage operations <variant-id>

List operation-level usage with request counts, error counts, and client breakdown.

Who: Member Admin Owner

feddi usage operation <variant-id> <operation-name>

Show usage detail for a specific operation.

Who: Member Admin Owner

Organizations & members

feddi org list

List your organizations.

Who: any signed-in user

feddi org view <org-id>

View organization details.

Who: Member Admin Owner

feddi member list <org-id>

List organization members.

Flags: --first <N> · --after <cursor>

Who: Member Admin Owner

feddi member invite <org-id> <email>

Invite a member.

Flags: --role <ADMIN|MEMBER> (default: MEMBER)

Who: Admin Owner

feddi member revoke-invite <invitation-id>

Revoke a pending invitation.

Who: Admin Owner

feddi member resend-invite <invitation-id>

Resend the email for a pending invitation.

Who: Admin Owner

feddi member deactivate <membership-id>

Suspend an active member. Admins cannot deactivate other Admins or Owners.

Who: Admin Owner

feddi member reactivate <membership-id>

Restore a previously deactivated member.

Who: Admin Owner

feddi member update-role <membership-id> <role>

Change a member's role. Promoting another Member to OWNER demotes the current Owner to ADMIN.

Who: Owner

Miscellaneous

feddi version

Print the CLI version and build info.

Who: no auth required