CreateSyncServerOptions
Defined in: packages/server/src/index.ts:80
Type Parameters
Section titled “Type Parameters”TRegistry
Section titled “TRegistry”TRegistry extends SyncTableRegistry
TDb extends PgAsyncDatabase<PgQueryResultHKT, RegistryRelations<TRegistry>> = PgAsyncDatabase<PgQueryResultHKT, RegistryRelations<TRegistry>>
Properties
Section titled “Properties”allowedOrigins?
Section titled “allowedOrigins?”
optionalallowedOrigins?:string[]
Defined in: packages/server/src/index.ts:123
applyFunctionGrantExecuteTo?
Section titled “applyFunctionGrantExecuteTo?”
optionalapplyFunctionGrantExecuteTo?: readonlystring[]
Defined in: packages/server/src/index.ts:169
The roles the INSTALLED apply function was generated with (pgxsinkit-generate --grant-execute-to <role>, ADR-0054). Default [] — owner-only, the default the CLI generates.
It is not a grant this server performs; it is how the server reproduces the artifact’s ADR-0018
fingerprint, which hashes the ACL along with the rest of the body. Generate with a grant and leave
this unset and every write fails PXS01 (stale artifact) — so the two lists must stay identical.
applyFunctionSchema?
Section titled “applyFunctionSchema?”
optionalapplyFunctionSchema?:string
Defined in: packages/server/src/index.ts:182
The schema the INSTALLED apply function lives in (pgxsinkit-generate --function-schema <schema>).
Default: unset — the artifact is generated unqualified and resolved through the connection’s
search_path.
It does two things at once, which is why one option drives both: the schema is part of the
fingerprinted body (the function names itself in its own self-check), AND it is how this server
QUALIFIES the call. Generate with --function-schema and leave this unset and the call goes out
unqualified — which either finds nothing (42883) or, worse, finds a same-named function elsewhere
on the search_path that then fails PXS01 against a fingerprint it does not carry. The two must
name the same schema.
db:
TDb
Defined in: packages/server/src/index.ts:88
deployment?
Section titled “deployment?”
optionaldeployment?:DeploymentProfile
Defined in: packages/server/src/index.ts:131
The startup query posture (ADR-0030). The apply function now verifies its own ADR-0018 fingerprint
in-body on every call (SQLSTATE PXS01 on drift), so there is no startup drift check to configure;
this governs only the RLS auth-helper verify and the operations-log presence resolution. Defaults
are the safe degradation posture (ADR-0030). See DeploymentProfile.
eventGate?
Section titled “eventGate?”
optionaleventGate?:EventGate
Defined in: packages/server/src/index.ts:138
The Event lane’s consent/entitlement gate (ADR-0053 decision 1): the lane’s one function, and so an
option here rather than a registry field (the registry stays declarative data only). Called once per
event, after its payload validated and its identity resolved, and before anything is enqueued; a refusal
is a per-event refused verdict. Absent → every well-formed event is allowed. See EventGate.
eventQueue?
Section titled “eventQueue?”
optionaleventQueue?:EventQueue
Defined in: packages/server/src/index.ts:153
The Event lane’s queue backend. Defaults to the shipped pgmq backend over this server’s own db
(createPgmqEventQueue), which is what makes an enqueue join the endpoint’s transaction. Override it to
run the lane on another backend, or to substitute a fake in tests.
healthCheck?
Section titled “healthCheck?”
optionalhealthCheck?:boolean| {path:string; }
Defined in: packages/server/src/index.ts:119
Health check endpoint. Enabled by default at /health; false disables it, { path } relocates it.
optionalhost?:string
Defined in: packages/server/src/index.ts:121
idleTimeoutSeconds?
Section titled “idleTimeoutSeconds?”
optionalidleTimeoutSeconds?:number
Defined in: packages/server/src/index.ts:122
logTimings?
Section titled “logTimings?”
optionallogTimings?:boolean
Defined in: packages/server/src/index.ts:160
Opt-in per-request timing log (default false). When on, each mutation and shape-proxy request emits
one compact [pgxsinkit-timing] line with an ISO-8601(ms, UTC) timestamp and phase durations, for
attributing wall-clock latency against the client’s syncDebug lines. Off by default — a pure
diagnostic surface that adds no standing query or latency when unset.
onEventsEnqueued?
Section titled “onEventsEnqueued?”
optionalonEventsEnqueued?:EventsEnqueuedHook
Defined in: packages/server/src/index.ts:147
Fired after an ingest request ENQUEUED at least one sub-batch (ADR-0053 amendment, 2026-08-02): the
deployment-agnostic seam a SERVERLESS deployment uses to nudge whatever endpoint runs the consumer’s
drainOnce(), so an interactive append drains in milliseconds instead of waiting for the next
scheduled tick. Fire-and-forget — it is called after the commit, its throw is caught and warn-logged,
and the scheduled sweep (not the nudge) is the delivery guarantee. Absent → nothing is nudged, which is
right for a deployment hosting the long-lived runner. See EventsEnqueuedHook.
onStatusChange?
Section titled “onStatusChange?”
optionalonStatusChange?: (status) =>void
Defined in: packages/server/src/index.ts:124
Parameters
Section titled “Parameters”status
Section titled “status”SyncRuntimeStatus
Returns
Section titled “Returns”void
operationsLog?
Section titled “operationsLog?”
optionaloperationsLog?:object
Defined in: packages/server/src/index.ts:115
enabled?
Section titled “enabled?”
optionalenabled?:boolean
optionalport?:number
Defined in: packages/server/src/index.ts:120
readPath?
Section titled “readPath?”
optionalreadPath?:object
Defined in: packages/server/src/index.ts:98
When set, the server serves the NATIVE read path’s control plane (ADR-0055): subscribe, stream-token re-mint, and the engine convergence barrier. Without it, none of those routes is registered and the deployment is write-only.
They share the single resolveAuthClaims adapter with the write path (ADR-0003), so read and write
authorization cannot diverge.
barrierMaxAgeSeconds?
Section titled “barrierMaxAgeSeconds?”
optionalbarrierMaxAgeSeconds?:number
How long the barrier answer may be cached. Default 0 — see createBarrierHandler.
engine
Section titled “engine”engine:
object
The Circuits engine’s control API — never client-reachable; only this process calls it.
engine.createShape()
Section titled “engine.createShape()”createShape(
request):Promise<CircuitsShapeHandle>
Register a shape and get the stream to follow — and renew that registration.
There is deliberately no renewShape: a renewal IS this call, repeated with the same
request.subscription on the same definition (fork ADR-0008). The engine answers the same
handle, counts nothing extra, and moves the lease forward. That is also why a create whose
response was lost can simply be sent again, and why the control plane’s token re-mint can renew
every live claim without a second route.
Two outcomes a caller must distinguish:
- 409 (CircuitsEngineError.status) — the id names a DIFFERENT shape already. One name, one shape; nothing was taken, and a retry will not change it.
- a different handle — the claim had lapsed or the shape was evicted, so this call re-subscribed rather than renewed. The stream the old grant named is not this one (ADR-0007).
The engine shares by definition: two identical bodies collapse onto one maintained stream and return the same handle. Nothing here has to check for that or cache against it — which is exactly why the shared tier’s predicate must be GENERATED. Two subscribers in one scope produce identical bodies only because neither’s identity reached the predicate; they are still two distinct subscriptions, because each names its own claim.
The answer is VALIDATED, not cast, for the same reason replicationState validates the barrier: an engine that acknowledges a create without saying which subscription it recorded or how long that subscription lives cannot be renewed or released by id at all, and defaulting either field would invent a lease this control plane was never promised.
Parameters
Section titled “Parameters”request
Section titled “request”Returns
Section titled “Returns”Promise<CircuitsShapeHandle>
engine.releaseShape()
Section titled “engine.releaseShape()”releaseShape(
shapeId,subscription):Promise<void>
Release ONE named subscription’s claim on a shape (DELETE /shapes/{id}?subscription=…).
Idempotent, and that is the whole point of naming the claim: releasing one that is already
gone is a no-op 200 rather than a decrement that steals another subscriber’s. A caller whose
response was lost may simply send it again.
There is no anonymous form here. The engine still accepts a bare DELETE /shapes/{id} as a
legacy refcount decrement, but it carries no claim identity and is not retry-safe, so this
client never issues one.
The shape itself survives its other subscribers and then follows the engine’s retention lifecycle (idle → dormant → evicted); this is a release, not a delete.
Parameters
Section titled “Parameters”shapeId
Section titled “shapeId”string
subscription
Section titled “subscription”string
Returns
Section titled “Returns”Promise<void>
engine.replicationState()
Section titled “engine.replicationState()”replicationState():
Promise<CircuitsReplicationState>
The engine’s convergence barrier (ADR-0056): where replication is, how many computed-but-undelivered subquery flips remain, and how many flip batches the engine gave up on.
The engine answers a sync field beside these and it is deliberately NOT read: it is the
__el_sync sentinel watermark — an i64 the engine’s conformance harness bumps and waits on as
a global quiescence fence — which no pgxsinkit database ever writes, so it is 0 everywhere and
says nothing about convergence.
pendingFlips > 0 means a revocation has been computed and not yet written to any stream,
which no wire-format watermark can see. That is the term the Electric wire could not express
at all, and the reason the barrier is read out of band rather than inferred from a position.
flipFailures > 0 means a batch was abandoned after exhausting its propagation retries:
those membership effects are gone rather than late. The engine keeps the abandoned batch’s
pendingFlips count held — so the waiting terms never falsely read converged — and latches
itself degraded: /ready answers 503, so do its membership-bearing routes, and a reaper
deletes every subquery shape stream. Recovery is an operator restart.
The answer is VALIDATED, not cast. An engine that does not report both counters cannot answer the question this barrier asks, and defaulting a missing term to zero would manufacture a converged reading out of an engine that never claimed one.
Returns
Section titled “Returns”Promise<CircuitsReplicationState>
entitlements?
Section titled “entitlements?”
optionalentitlements?:EntitlementSet
The live entitlement set backing the shared tier. Omit when the registry declares no shared shape — a shared subscription is then refused with that reason rather than silently allowed.
key:
CryptoKey
The stream-token signing key, shared with the edge.
resolveShapeParams?
Section titled “resolveShapeParams?”
optionalresolveShapeParams?: (request) =>Record<string,unknown> |undefined
Optional per-request extra params passed to the private tier’s row filters.
Parameters
Section titled “Parameters”request
Section titled “request”Request
Returns
Section titled “Returns”Record<string, unknown> | undefined
ttlSeconds?
Section titled “ttlSeconds?”
optionalttlSeconds?:number
Per-deployment override of ADR-0055’s 5-minute token lifetime.
registry
Section titled “registry”registry:
TRegistry
Defined in: packages/server/src/index.ts:87
resolveAuthClaims?
Section titled “resolveAuthClaims?”
optionalresolveAuthClaims?: (request) => {[key:string]:unknown;app_metadata?: {[key:string]:unknown;roles?:string[]; };sub?:string; } |Promise<{[key:string]:unknown;app_metadata?: {[key:string]:unknown;roles?:string[]; };sub?:string; } |null> |null
Defined in: packages/server/src/index.ts:89
Parameters
Section titled “Parameters”request
Section titled “request”Request
Returns
Section titled “Returns”{[key: string]: unknown; app_metadata?: {[key: string]: unknown; roles?: string[]; }; sub?: string; } | Promise<{[key: string]: unknown; app_metadata?: {[key: string]: unknown; roles?: string[]; }; sub?: string; } | null> | null