Skip to main content

New Edge PDP Architecture

What runs inside the New Edge PDP container, which component is responsible for what, and the path a single authorization request takes.

Everything runs inside one container. The only externally exposed listeners are the authorization API and the health endpoint.

Architecture of the New Edge PDP: your app and orchestrator on the left, the single New Edge PDP container holding the authorization API, OPA, the health server, the query and bundle loopbacks, the embedded database, the change-ingest worker and the NATS leaf, with Permit.io and your policy store on the right

Click the diagram to enlarge it.

Reading the diagram

The diagram labels the change stream by its internal name, the WAL (write-ahead log). LOCAL_WAL is this container's own durable copy of it. Elsewhere in these pages it is called the change stream.


What runs where

ComponentKindRole
Authorization APIIn-processThe public REST surface on port 7000. Opens only once the PDP is ready.
OPA policy engineSupervised child processEvaluates Rego. Bound to loopback only — never reachable from outside the container.
Embedded databaseIn-process (SurrealDB over RocksDB)Your environment's fact graph — users, tenants, resource instances, relationships — on disk.
NATS leaf nodeSupervised child processDurable, on-disk event store. Holds the link to Permit's control plane.
Change ingest and repairIn-process taskApplies incoming changes to the embedded database; detects and repairs gaps.
Query / bundle loopbacksIn-processServe OPA its graph data and its policy bundle over 127.0.0.1.
Health and readinessIn-processPort 7001. Answers throughout startup, including a long cold start.

Ports

PortBound toPurpose
7000All interfacesAuthorization API — the only port your services need
7001All interfacesHealth and readiness — the port your orchestrator probes
7002LoopbackQuery loopback: serves OPA its graph data
7003LoopbackBundle loopback: serves OPA its Rego bundle
8181LoopbackOPA
4222 / 8222LoopbackNATS leaf client and monitoring

Only 7000 and 7001 are exposed by the container image. Everything else is reachable solely from inside it.


The decision path

client → :7000 authorization API
→ 127.0.0.1 OPA
→ 127.0.0.1 query loopback
→ embedded database (local disk)

Every hop is loopback or local disk. No step in answering an authorization query contacts Permit's API, by construction — the New Edge PDP has no control plane other than its event stream, and cannot reach api.permit.io for a decision even if it wanted to.

This is also what separates policy evaluation from graph traversal. OPA evaluates the Rego policy, but whenever that policy needs to know whether a user reaches a resource through a chain of roles and relationships, it calls out to the query loopback, which answers from the embedded database. Relationship queries run against a database built for them rather than against a JSON document held in memory.


Separation of duties

The container is deliberately split so that the thing serving decisions is never blocked by the thing keeping data fresh:

  • The request path — authorization API, OPA, query loopback, embedded database — only ever reads.
  • The sync path — NATS leaf, change ingest, gap detector, rebuild orchestrator — only ever writes, on its own tasks.

They meet at the embedded database, which is why a control-plane outage costs freshness but never availability, and why a rebuild can run underneath a PDP that is still answering. See How It Works for what happens along the sync path.