# Known Issues

This page lists known user-visible limitations in pgGraph 1.1. See
[Release Notes](./release-notes) for resolved issues and
[Roadmap](./roadmap) for planned expansion.

## Operations

### External scheduling is required outside the packaged Docker setup

pgGraph exposes bounded, concurrency-safe maintenance entry points, but it does
not run an always-on scheduler inside every PostgreSQL installation. The
packaged Docker image configures `pg_cron`. Other installations must schedule
`graph.run_scheduled_maintenance()` with `pg_cron` or an external scheduler.

Without a scheduler, reads remain available, but pending trigger-sync work,
overlay compaction, and cleanup do not run automatically. Follow the setup,
health, retry, and failure guidance in
[Sync And Maintenance](/user_guide/sync-and-maintenance#scheduled-maintenance).

## Access Control

### RLS protects results, not every timing or resource side channel

pgGraph 1.1 excludes caller-hidden node and relationship identities before
they can affect observable topology. The resource governor may still charge
projection entries examined while constructing or applying that visibility
boundary. The supported contract is PostgreSQL-like result and topology
visibility; pgGraph does not claim formal timing or resource-exhaustion
noninterference between roles with different policies.

### Tenant scope requires the session-setting path under enforcement

For a graph whose tables are registered with `tenant_column` rather than
pinned to a single graph-level tenant, an explicit tenant argument is a
caller-supplied value, not one verified against the calling role's identity.
While `graph.enforce_tenant_scope = on` (the default), pgGraph refuses an
explicit tenant argument for such a graph and requires the session tenant
(`graph.tenant_setting`) instead. pgGraph cannot verify that a session's
tenant setting reflects who is actually connected; that trust boundary
belongs to whatever sets the session GUC before the caller's own queries run.
See [Tenant Scope](/user_guide/administration-and-security#tenant-scope) for
the full boundary and mitigation guidance.

## Query Compatibility

### GQL writes accept one parameter object per call

The 1.0 mapped GQL write profile creates, merges, updates, or deletes one node
or relationship per `graph.gql()` call. It does not expose a multi-row mutation
or `UNWIND` write surface. An adapter that calls `graph.gql()` once per item
therefore pays repeated client round trips and parse, bind, ACL, and SPI work.

For bulk ingestion in 1.0, write registered PostgreSQL source tables directly
with set-based DML, commit, and apply sync once:

```sql
BEGIN;

INSERT INTO app.entities (id, name)
VALUES
  ('n-1', 'Ada'),
  ('n-2', 'Grace')
ON CONFLICT (id) DO UPDATE
SET name = EXCLUDED.name;

COMMIT;

SELECT * FROM graph.apply_sync();
```

PostgreSQL remains authoritative for constraints, triggers, ACLs, RLS, MVCC,
and partition routing. In persisted `mutable_overlay` mode, committed edge
changes become durable projection segments after sync without a full graph
rebuild. Applications with the default pending-sync query freshness may let the
next topology read catch up instead of calling `graph.apply_sync()` explicitly.

A bounded, set-based graph mutation API is the proposed
[post-1.1 roadmap direction](/roadmap#proposed-post-1-1-focus-bounded-batched-mutations).

### GQL and openCypher support are bounded profiles

`graph.gql()` implements the generated [GQL 1.0 profile](/user_guide/gql-profile),
not full ISO GQL. `graph.cypher()` accepts only the overlapping compatibility
profile and does not claim full openCypher support. Unsupported constructs fail
with a stable SQLSTATE and actionable guidance rather than being interpreted
with approximate semantics.

SQL/PGQ `GRAPH_TABLE` is not part of the PostgreSQL 14–18 contract. PostgreSQL
19 integration remains on the [Roadmap](./roadmap).

## Resource Scope

### Limits are per operation and backend, not a cluster-wide memory quota

Build, load, query, synchronization, compaction, and supported analytics enforce
their documented byte, row, work, disk, and elapsed-time policies. PostgreSQL's
own buffer cache, executor memory, and other sessions remain governed by
PostgreSQL configuration and operating-system controls. `graph.memory_limit_mb`
therefore does not replace cluster-wide capacity planning.

Use `graph.resource_status()`, `graph.build_resource_status()`, PostgreSQL
`statement_timeout`, and the production-shaped RSS/PSS release evidence when
sizing concurrent workloads. See [Configuration](/user_guide/configuration)
and [Troubleshooting](/user_guide/troubleshooting#query-or-maintenance-hits-a-resource-limit).

## Reporting A New Issue

Include the pgGraph version, PostgreSQL major, platform, exact SQLSTATE and
`PGxxx` diagnostic, relevant `graph.status()`/`graph.resource_status()` output,
and a minimal source schema. Do not include credentials or production data.
