doc-store-pg/specs/ArchitectureBlueprint.md

1996 lines
44 KiB
Markdown
Executable file
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ArchitectureBlueprint.md
## Repository
`doc-store-pg`
## Status
Architecture blueprint / research baseline.
This document defines the initial technical architecture for `doc-store-pg`. It is intentionally a blueprint rather than a frozen implementation specification. The architecture should remain stable enough to support reproducible experimentation while leaving individual components replaceable.
The central design question is:
> Can document storage become a composable capability of a CloudNativePG/PostgreSQL platform while preserving MongoDB-compatible application surfaces, strong multitenancy choices, PostgreSQL-native access, and an evidence-driven path to long-term optimization?
---
## 1. Architectural Intent
`doc-store-pg` should provide a document-oriented data surface on top of PostgreSQL without turning PostgreSQL into an opaque implementation detail.
The architecture therefore preserves two first-class access paths:
1. **Document access** through MongoDB-compatible protocols and semantics.
2. **PostgreSQL access** through SQL and PostgreSQL-native tooling.
The project should prefer composition of upstream technologies over reimplementation.
The initial architecture is built around:
- Kubernetes as the runtime substrate
- CloudNativePG as the PostgreSQL lifecycle and HA layer
- PostgreSQL 18+ as the initial database baseline
- DocumentDB PostgreSQL extensions as the primary document engine candidate
- DocumentDB Gateway and FerretDB as interchangeable MongoDB-compatible gateway candidates
- PostgreSQL-native JSONB as a baseline and fallback document representation
- Kubernetes-native configuration and observability
- explicit multitenancy and tenant-placement policies
- reproducible benchmark and conformance workloads
The architecture is designed so that these choices can be challenged by research rather than becoming permanent assumptions.
---
## 2. Architecture Principles
### 2.1 PostgreSQL Remains Visible
Document functionality is added to PostgreSQL; it does not replace the PostgreSQL model.
Applications or services may intentionally use:
- MongoDB-compatible document APIs
- SQL
- JSON/JSONB queries
- BSON/document functions
- relational joins
- PostgreSQL transactions
- PostgreSQL extensions
This enables hybrid relational/document workloads to be treated as a core capability rather than an accidental escape hatch.
### 2.2 Composition Before Reimplementation
Existing open-source implementations should be evaluated before new equivalents are written.
In particular:
- BSON storage and document semantics should initially come from DocumentDB.
- MongoDB wire-protocol translation should initially come from DocumentDB Gateway or FerretDB.
- PostgreSQL HA, failover, replication, backup integration, and cluster lifecycle should remain CloudNativePG responsibilities.
`doc-store-pg` should only implement functionality itself where integration, compatibility, policy, observability, or research requirements cannot reasonably be satisfied upstream.
### 2.3 Gateways Are Replaceable
MongoDB compatibility is an interface, not a hard dependency on one gateway.
```text
MongoDB client
|
+--> DocumentDB Gateway --> PostgreSQL + DocumentDB
|
+--> FerretDB -----------> PostgreSQL + DocumentDB
```
Additional gateway implementations may later be evaluated using the same conformance and benchmark suites.
### 2.4 Tenant Placement Is Explicit
Multitenancy is not represented by a boolean flag.
A tenant should have an explicit placement/isolation model:
```text
POOLED
NAMESPACE
DATABASE
DEDICATED
```
Future versions may add distributed or federated placement modes.
### 2.5 Compatibility Is Measured
"MongoDB compatible" is not considered a binary architectural property.
Compatibility should be measured separately for:
- wire protocol
- CRUD operations
- query semantics
- aggregation semantics
- indexing
- drivers
- tools
- transactions
- sessions
- change streams
- errors and edge cases
- application-level behavior
### 2.6 Evidence Before Optimization
Architectural decisions that materially affect compatibility, tenancy, performance, or operations should be benchmarkable.
The system should make it possible to ask:
> Which configuration is better for this workload and why?
rather than:
> Which database do we generally prefer?
### 2.7 Upstream Escape Hatches Remain Available
DocStorePG should not create unnecessary lock-in to its own abstractions.
A deployment should remain understandable through normal:
- Kubernetes resources
- CloudNativePG resources
- PostgreSQL tools
- DocumentDB tooling
- MongoDB-compatible clients
The project should add useful abstraction, not hide the underlying systems.
---
# 3. System Context
```mermaid
flowchart TB
subgraph Clients
A[MongoDB-compatible applications]
B[PostgreSQL / SQL applications]
C[Operations and automation]
D[Benchmark and conformance clients]
end
subgraph DocStorePG["doc-store-pg capability"]
G[MongoDB-compatible Gateway]
P[PostgreSQL Access]
T[Tenant / Placement Policy]
O[Observability]
X[Benchmark & Conformance Hooks]
end
subgraph DataPlane["CloudNativePG Data Plane"]
CNPG[CloudNativePG Cluster]
PG[(PostgreSQL)]
DDB[DocumentDB Extensions]
JSONB[Native JSONB]
end
A --> G
B --> P
C --> T
D --> X
G --> PG
P --> PG
T --> CNPG
X --> G
X --> P
CNPG --> PG
PG --- DDB
PG --- JSONB
PG --> O
G --> O
```
The important architectural point is that **DocStorePG is not initially a database engine**.
It is a capability profile formed from:
```text
PostgreSQL
+ document engine
+ compatible gateway
+ CloudNativePG operations
+ tenancy model
+ policy
+ observability
+ conformance
+ benchmarks
```
---
# 4. Layer Model
The initial architecture is divided into seven layers.
```text
L7 Research & Evidence
benchmarks, conformance, experiments, results
L6 DocStorePG Control
profiles, tenancy policy, placement, configuration
L5 Application Interfaces
MongoDB wire protocol, PostgreSQL protocol, admin APIs
L4 Document Semantics
BSON, document CRUD, query, aggregation, indexing
L3 PostgreSQL Data Platform
SQL, JSONB, transactions, RLS, extensions
L2 CloudNativePG Operations
cluster lifecycle, HA, replication, backup hooks, services
L1 Kubernetes Infrastructure
scheduling, storage, networking, secrets, resources
```
A change at one layer should be measurable without requiring unrelated layers to change.
For example, replacing FerretDB with DocumentDB Gateway should not require changing the PostgreSQL cluster, tenant workload, or benchmark definitions.
---
# 5. Reference Runtime Architecture
## 5.1 Default Reference Deployment
```mermaid
flowchart LR
MC[Mongo Client]
SC[SQL Client]
subgraph GW["Gateway Tier"]
G1[DocumentDB Gateway]
end
subgraph K8S["Kubernetes"]
subgraph CNPG["CloudNativePG Cluster"]
RW[(Primary)]
R1[(Replica)]
R2[(Replica)]
end
end
MC -->|MongoDB wire protocol| G1
G1 -->|PostgreSQL operations| RW
SC -->|PostgreSQL protocol| RW
RW -->|streaming replication| R1
RW -->|streaming replication| R2
```
The default research deployment should use three PostgreSQL instances when testing HA behavior and may use a single PostgreSQL instance for local functional development.
The gateway tier should remain separately deployable from PostgreSQL so that:
- gateway resource consumption can be measured independently
- multiple gateway implementations can be compared
- gateway replicas can scale independently
- gateway failures can be distinguished from database failures
- protocol translation overhead can be isolated
---
## 5.2 PostgreSQL Baseline
The initial baseline should target PostgreSQL 18 or later.
This is particularly useful because CloudNativePG's ImageVolume extension mechanism uses PostgreSQL 18's `extension_control_path` support and permits compatible extension images to be mounted dynamically into cluster pods.
The implementation should pin exact versions in deployment profiles rather than using floating image tags.
Example conceptual lock information:
```yaml
platform:
postgresql: "18.x"
cloudnativepg: "<pinned>"
kubernetes: "<supported-version>"
extensions:
documentdb:
version: "<pinned>"
image: "<immutable-image-reference>"
gateway:
implementation: documentdb
version: "<pinned>"
```
The exact versions belong in machine-readable deployment profiles, not permanently in this blueprint.
---
# 6. Extension Architecture
## 6.1 Primary Document Engine
DocumentDB is the initial primary candidate because its architecture already separates document functionality into PostgreSQL-oriented components:
```text
pg_documentdb_core
|
+-- BSON storage and primitives
pg_documentdb
|
+-- document API
+-- CRUD
+-- queries
+-- indexes
+-- aggregation functionality
pg_documentdb_gw
|
+-- MongoDB wire protocol
+-- authentication/session gateway behavior
```
DocStorePG should treat these as upstream capabilities.
## 6.2 Extension Packaging
Preferred path:
```text
OCI extension image
|
v
CloudNativePG ImageVolume
|
v
PostgreSQL pod
|
v
CREATE/UPDATE EXTENSION
```
This should be preferred over building permanently customized PostgreSQL images where the required extension can be safely managed as an image-volume extension.
A custom PostgreSQL image remains an allowed fallback for:
- unsupported extension packaging
- experimental builds
- debugging
- compatibility tests
- extension combinations that cannot yet use ImageVolumes
## 6.3 Extension Lifecycle
Extension lifecycle must be treated separately from application schema lifecycle.
Required states:
```text
available
installed
configured
upgradable
upgraded
rollback-tested
```
The benchmark program should eventually include:
- extension install time
- upgrade behavior
- PostgreSQL major-upgrade interaction
- replica behavior
- recovery behavior
- incompatible-extension failure behavior
---
# 7. Gateway Architecture
## 7.1 Gateway Contract
A gateway accepts MongoDB-compatible client traffic and maps it to the PostgreSQL-backed document engine.
The gateway layer must be independently observable.
Required gateway metrics should eventually include:
- request count
- command type
- response latency
- upstream PostgreSQL latency
- translation latency where measurable
- active connections
- connection establishment rate
- rejected connections
- authentication failures
- protocol errors
- unsupported commands
- PostgreSQL errors
- memory
- CPU
- network throughput
## 7.2 Candidate A — DocumentDB Gateway
DocumentDB Gateway is the reference path closest to the DocumentDB implementation itself.
Use it as the initial compatibility baseline.
## 7.3 Candidate B — FerretDB
FerretDB 2.x uses PostgreSQL with the DocumentDB extension as its backend and translates MongoDB wire-protocol operations for clients.
It should be preserved as an alternative gateway because it permits a controlled experiment:
```text
same client
same workload
same PostgreSQL
same DocumentDB engine
different gateway
```
This isolates gateway behavior from storage-engine behavior.
## 7.4 Gateway Selection Profile
Conceptual configuration:
```yaml
gateway:
enabled: true
implementation: documentdb
replicas: 2
resources:
profile: standard
service:
exposure: cluster-internal
observability:
enabled: true
```
Alternative:
```yaml
gateway:
implementation: ferretdb
```
The actual configuration mechanism may initially be Helm/Kustomize values rather than a custom CRD.
---
# 8. Native PostgreSQL Surface
MongoDB compatibility should never be the only supported path.
DocStorePG should deliberately preserve a native SQL surface.
```mermaid
flowchart TD
DOC[(Document data)]
M[MongoDB-compatible API]
S[SQL]
H[Hybrid application]
M --> DOC
S --> DOC
H --> M
H --> S
```
This enables research into workloads such as:
```sql
SELECT
c.customer_id,
d.document
FROM customers c
JOIN device_documents d
ON d.customer_id = c.customer_id
WHERE c.contract_status = 'active'
AND document_matches_capability(d.document, 'cooling');
```
The precise document functions may differ, but the architectural requirement is that document data remain usable from SQL where the upstream engine supports it.
This hybrid access mode is one of the central differentiators to test.
---
# 9. Baseline Storage Profiles
DocStorePG should initially define stable comparable storage profiles.
## P0 — Native PostgreSQL JSONB
```text
PostgreSQL
+ JSONB
+ native PostgreSQL indexes
+ no Mongo gateway
```
Purpose:
- establish the minimum PostgreSQL document baseline
- measure what PostgreSQL already provides without a compatibility layer
## P1 — DocumentDB / Native PostgreSQL Interface
```text
PostgreSQL
+ DocumentDB extensions
+ direct PostgreSQL access
```
Purpose:
- isolate DocumentDB storage and document semantics
- measure document-engine overhead without Mongo wire translation
## P2 — DocumentDB Gateway
```text
Mongo client
|
DocumentDB Gateway
|
PostgreSQL + DocumentDB
```
Purpose:
- primary MongoDB compatibility candidate
## P3 — FerretDB Gateway
```text
Mongo client
|
FerretDB
|
PostgreSQL + DocumentDB
```
Purpose:
- alternative compatibility path
- gateway comparison
## M0 — Native MongoDB Reference
```text
Mongo client
|
MongoDB
```
Purpose:
- external reference implementation
- semantic compatibility oracle where appropriate
- performance and operational comparator
These profile identifiers should remain stable so benchmark results can be compared over time.
---
# 10. Multitenancy Architecture
Multitenancy is a first-class architecture dimension.
The initial tenant-placement ladder is:
```text
T0 POOLED
T1 NAMESPACE
T2 DATABASE
T3 DEDICATED
```
These identifiers should remain stable in benchmark datasets.
## 10.1 T0 — Pooled
Multiple tenants share document structures.
```text
PostgreSQL database
|
+-- shared document collection/table
|
+-- tenant_id = A
+-- tenant_id = B
+-- tenant_id = C
```
Required design goal:
> Tenant identity should be enforced as deeply as the selected interface permits.
For PostgreSQL-native access, this should include evaluating Row-Level Security.
Illustrative pattern:
```sql
ALTER TABLE documents ENABLE ROW LEVEL SECURITY;
CREATE POLICY tenant_isolation
ON documents
USING (
tenant_id = current_setting('docstorepg.tenant_id')::uuid
);
```
### Research questions
- Can tenant identity propagate safely through a MongoDB-compatible gateway?
- Does the document engine expose sufficient hooks for RLS-based enforcement?
- Can a gateway accidentally bypass RLS through privileged database roles?
- How can connection pooling safely preserve tenant context?
- What performance cost does RLS introduce?
- Can tenant-aware compound indexes prevent cross-tenant hot spots?
- How do backup and restore work for a single pooled tenant?
## 10.2 T1 — Namespace
Tenants receive PostgreSQL schemas or another logically separate namespace.
```text
cluster
|
+-- database
|
+-- tenant_a schema
+-- tenant_b schema
+-- tenant_c schema
```
Advantages to evaluate:
- stronger logical separation than pooled rows
- separate objects and indexes
- tenant-specific schema customization
- relatively low compute overhead compared with dedicated clusters
Risks to evaluate:
- object proliferation
- PostgreSQL catalog growth
- migration complexity
- gateway mapping complexity
- uncertain fit with document-engine assumptions
- backup/restore granularity
T1 must be treated as an experiment until compatibility with the selected document engine and gateway is proven.
## 10.3 T2 — Database
Each tenant receives a separate PostgreSQL database inside one CloudNativePG cluster.
```text
CloudNativePG cluster
|
+-- tenant_a database
+-- tenant_b database
+-- tenant_c database
```
CloudNativePG can declaratively manage additional databases and their extensions/schemas.
This mode should evaluate:
- per-tenant ownership
- per-database extensions
- migration lifecycle
- database count scaling
- connection overhead
- catalog/resource overhead
- backup/restore behavior
- gateway routing
- tenant-specific configuration
- noisy-neighbour effects
The compute and storage failure domain remains shared.
## 10.4 T3 — Dedicated
Each tenant receives a dedicated CloudNativePG-backed DocStorePG deployment.
```mermaid
flowchart LR
A[Tenant A] --> CA[DocStorePG Cluster A]
B[Tenant B] --> CB[DocStorePG Cluster B]
C[Tenant C] --> CC[DocStorePG Cluster C]
```
This mode provides the strongest initial isolation boundary.
Potential isolation includes:
- PostgreSQL process
- PostgreSQL database
- gateway
- CPU request/limit
- memory request/limit
- persistent storage
- Kubernetes scheduling
- secrets
- service identity
- network policy
- backup policy
- failure domain
The primary downside is fleet overhead.
T3 is expected to be most relevant to:
- large enterprise tenants
- regulated workloads
- tenants requiring special extensions
- tenants requiring independent maintenance windows
- high-volume "whale" tenants
- contractual isolation requirements
---
# 11. Tenant Placement as a Lifecycle
The important abstraction is not merely selecting one of T0T3.
The longer-term architecture should explore tenant mobility:
```mermaid
stateDiagram-v2
[*] --> Pooled
Pooled --> Namespace
Pooled --> Database
Namespace --> Database
Database --> Dedicated
Pooled --> Dedicated
Dedicated --> Database
Database --> Pooled
```
Not all transitions need to be supported initially.
The strategic goal is:
> Keep the application-facing document contract as stable as possible while tenant placement changes underneath it.
This is DocStorePG's initial conceptual answer to some of the problems that MongoDB solves with shard placement.
It is not initially intended to reproduce MongoDB sharding.
---
# 12. Explicit Sharding Boundary
MongoDB provides native horizontal sharding in which data can be distributed across shards and routed through a unified cluster interface.
CloudNativePG's normal architecture is a PostgreSQL primary/standby cluster. It is not by itself a transparent horizontally sharded write architecture.
Therefore:
> DocStorePG V1 must not claim MongoDB-equivalent horizontal sharding.
The initial architecture deliberately stops here:
```text
single DocStorePG deployment
|
+-- primary
+-- replicas
```
and permits multiple independent placements:
```text
DocStorePG A
DocStorePG B
DocStorePG C
```
A future research track may investigate a placement/router layer:
```mermaid
flowchart TD
APP[Application]
R[Tenant Router]
A[DocStorePG Placement A]
B[DocStorePG Placement B]
C[DocStorePG Placement C]
APP --> R
R --> A
R --> B
R --> C
```
That work should only begin once there is evidence that it solves a problem not already better solved by:
- MongoDB sharding
- Citus or another PostgreSQL distribution technology
- application-level partitioning
- independent tenant clusters
- another existing distributed database
---
# 13. Proposed DocStorePG Control Surface
DocStorePG should not immediately create a Kubernetes operator.
The first implementation should prefer:
```text
Helm / Kustomize
+ CloudNativePG CRDs
+ standard Kubernetes resources
+ benchmark profiles
+ explicit configuration files
```
Only after recurring orchestration requirements emerge should a DocStorePG CRD/operator be justified.
A possible future API is documented here to establish architectural vocabulary.
## 13.1 Future `DocStore` Resource
```yaml
apiVersion: docstorepg.io/v1alpha1
kind: DocStore
metadata:
name: application-documents
spec:
postgres:
profile: ha-standard
documentEngine:
implementation: documentdb
gateway:
implementation: documentdb
replicas: 2
interfaces:
mongodb: true
postgresql: true
tenancy:
defaultPlacement: pooled
observability:
enabled: true
```
## 13.2 Future `DocStoreTenant` Resource
```yaml
apiVersion: docstorepg.io/v1alpha1
kind: DocStoreTenant
metadata:
name: acme
spec:
storeRef: application-documents
placement:
mode: database
resources:
class: standard
compatibility:
profile: mongodb-default
```
These resources are **design sketches**, not implementation commitments.
---
# 14. Configuration Profiles
Configuration should be grouped into composable profiles.
```text
profiles/
├── platform/
│ ├── local-single.yaml
│ ├── ha-small.yaml
│ └── ha-standard.yaml
├── engine/
│ ├── jsonb.yaml
│ └── documentdb.yaml
├── gateway/
│ ├── none.yaml
│ ├── documentdb.yaml
│ └── ferretdb.yaml
├── tenancy/
│ ├── pooled.yaml
│ ├── namespace.yaml
│ ├── database.yaml
│ └── dedicated.yaml
└── workload/
├── document-crud.yaml
├── aggregation.yaml
└── hybrid.yaml
```
A benchmark environment can then be expressed as composition:
```text
platform/ha-small
+ engine/documentdb
+ gateway/ferretdb
+ tenancy/pooled
+ workload/document-crud
```
This makes experiments easier to reproduce and diff.
---
# 15. Security Architecture
The security model should be layered.
```text
Kubernetes identity and RBAC
|
NetworkPolicy / service exposure
|
gateway authentication
|
PostgreSQL authentication
|
PostgreSQL role / database / schema privileges
|
Row-Level Security where applicable
|
document/application authorization
```
## 15.1 Security Rules
1. Gateway database credentials should not use PostgreSQL superuser privileges in production profiles.
2. `BYPASSRLS` roles must not be used for pooled tenant traffic where RLS is part of the tenant boundary.
3. Tenant context must be explicit and auditable.
4. Connection pooling must not leak tenant context between sessions.
5. PostgreSQL direct access must not silently bypass the intended Mongo-facing security model.
6. Mongo-compatible and SQL-facing identities must be mapped deliberately.
7. Secrets should be provided through Kubernetes-native secret mechanisms or external secret-management integration.
8. External service exposure should be opt-in.
9. NetworkPolicy should be part of production reference profiles.
10. Security tests belong in the conformance suite.
---
# 16. Identity Propagation
Tenant-aware pooled operation creates an important architecture problem:
```text
MongoDB client identity
|
v
Mongo gateway
|
v
PostgreSQL session identity
|
v
RLS / database policy
```
DocStorePG should explicitly test multiple strategies.
### Strategy A — Database Role Mapping
One PostgreSQL role per tenant or tenant class.
Potential strength:
- database-native identity
Potential weakness:
- large role counts
- connection-pool complexity
### Strategy B — Session Tenant Context
A trusted gateway sets a PostgreSQL session variable such as:
```sql
SET docstorepg.tenant_id = '...';
```
RLS reads that context.
Potential strength:
- scalable logical identity
Potential weakness:
- gateway becomes security-critical
- session reset must be flawless
### Strategy C — Database-per-Tenant Routing
Gateway selects the tenant database.
Potential strength:
- stronger logical boundary
Potential weakness:
- routing and connection-pool fragmentation
No strategy should be declared canonical until tested.
---
# 17. Network Architecture
Default production stance:
```text
Mongo endpoint: cluster-internal
PostgreSQL endpoint: cluster-internal
admin endpoints: cluster-internal
metrics endpoints: monitoring namespace / authorized collectors
external exposure: explicit profile only
```
Conceptual Kubernetes services:
```text
docstore-mongo-rw
docstore-postgres-rw
docstore-postgres-ro
docstore-metrics
```
The exact service structure should follow the selected upstream gateway and CloudNativePG conventions.
---
# 18. High Availability
CloudNativePG should own PostgreSQL HA.
```mermaid
flowchart LR
GW[Gateway replicas]
SVC[CNPG RW Service]
P[(Primary)]
R1[(Replica)]
R2[(Replica)]
GW --> SVC
SVC --> P
P --> R1
P --> R2
```
DocStorePG should test gateway behavior during PostgreSQL failover.
Important questions:
- Does the gateway reconnect automatically?
- What do clients observe?
- Which operations fail?
- Are retries safe?
- How do transactions behave?
- How quickly does service recover?
- Does MongoDB client retry behavior interact correctly with PostgreSQL failover?
- Does the gateway retain stale connections?
Failover testing belongs in the benchmark program.
---
# 19. Read Scaling
CloudNativePG provides read-only service patterns through replicas.
DocStorePG must not assume MongoDB-style read preferences map automatically to PostgreSQL read replicas.
Possible future mapping:
```text
Mongo read preference
|
v
Gateway policy
|
+--> primary
|
+--> CNPG read-only service
```
This requires explicit semantic research around:
- consistency
- replication lag
- transaction semantics
- session guarantees
- MongoDB driver expectations
- failover
Until proven, primary routing should be the correctness baseline.
---
# 20. Backup and Recovery
Backup architecture must distinguish between:
```text
cluster recovery
database recovery
tenant recovery
collection recovery
document recovery
```
CloudNativePG provides cluster-oriented PostgreSQL backup/recovery mechanisms; the DocumentDB Kubernetes Operator also has its own evolving backup abstractions.
DocStorePG should not assume that cluster-level backup automatically satisfies tenant-level recovery requirements.
Research must measure:
- backup duration
- backup size
- restore duration
- point-in-time recovery
- tenant-specific restore
- restoring one tenant from a pooled dataset
- restoring database-per-tenant
- dedicated-cluster restore
- Mongo-compatible application recovery behavior
Tenant recoverability is an important factor in choosing T0T3.
---
# 21. Observability Architecture
Observability should expose each layer independently.
```mermaid
flowchart LR
C[Client]
G[Gateway]
P[PostgreSQL]
K[Kubernetes]
B[Benchmark Harness]
C --> G --> P
G --> M[Metrics]
P --> M
K --> M
B --> M
G --> L[Logs]
P --> L
K --> L
M --> O[Observability Backend]
L --> O
```
Minimum metric categories:
### PostgreSQL
- transactions
- query latency
- query count
- locks
- connections
- cache hit behavior
- WAL generation
- checkpoint behavior
- replication lag
- table/index size
- I/O
- CPU
- memory
### Gateway
- operations
- command types
- latency
- failures
- unsupported requests
- active connections
- authentication
- CPU
- memory
### Kubernetes
- pod restarts
- scheduling
- CPU requests/usage
- memory requests/usage
- storage
- network
- failovers
- PVC behavior
### Tenant
Where possible:
- requests per tenant
- storage per tenant
- latency per tenant
- error rate per tenant
- resource share
- noisy-neighbour indicators
### Benchmark
Every benchmark run must capture enough environment metadata to explain the result.
---
# 22. Benchmark and Conformance Plane
The benchmark plane is part of the architecture, not an external one-off tool.
```mermaid
flowchart TB
W[Workload Catalog]
R[Runner]
M0[MongoDB Reference]
P0[PostgreSQL JSONB]
P1[DocumentDB Native]
P2[DocumentDB Gateway]
P3[FerretDB]
C[Comparator]
E[(Evidence Store)]
W --> R
R --> M0
R --> P0
R --> P1
R --> P2
R --> P3
M0 --> C
P0 --> C
P1 --> C
P2 --> C
P3 --> C
C --> E
```
Benchmark code should support deterministic seeds where possible.
Every result should include:
```yaml
run:
id: ...
timestamp: ...
gitCommit: ...
workload: ...
seed: ...
environment:
kubernetes: ...
nodes: ...
cpu: ...
memory: ...
storageClass: ...
software:
mongodb: ...
postgresql: ...
cloudnativepg: ...
documentdb: ...
gateway: ...
profile:
storage: P2
tenancy: T0
dataset:
tenants: ...
documents: ...
averageDocumentSize: ...
result:
throughput: ...
latencyP50: ...
latencyP95: ...
latencyP99: ...
errors: ...
```
This structure should evolve into a formal benchmark schema.
---
# 23. Differential Conformance Testing
For compatible operations, DocStorePG should support differential testing.
```text
request
|
+------> MongoDB ----------> result A
|
+------> DocStorePG -------> result B
|
v
semantic comparator
```
Comparison dimensions:
- returned data
- BSON types
- null/missing behavior
- ordering
- update results
- aggregation results
- errors
- error categories/codes
- transaction outcome
- session behavior
- index behavior
Differences should be classified as:
```text
IDENTICAL
EQUIVALENT
DOCUMENTED_DIFFERENCE
UNSUPPORTED
INCORRECT
UNKNOWN
```
A compatibility score must not hide important individual differences.
---
# 24. Workload Classes
The architecture should support at least these benchmark workload classes.
## W0 — Basic CRUD
- insert
- find by ID
- update
- delete
- bulk operations
## W1 — Flexible Schema
- optional fields
- heterogeneous structures
- schema evolution
- large/small documents
## W2 — Nested Documents
- nested objects
- arrays
- array element updates
- nested predicates
## W3 — Indexing
- single-field
- compound
- nested
- wildcard/dynamic-field equivalents
- low/high cardinality
- many-index write cost
## W4 — Aggregation
- filtering
- projection
- grouping
- sorting
- unwind
- lookup/join-like behavior
- facets
## W5 — Transactions
- single-document
- multi-document
- concurrent updates
- abort/retry behavior
## W6 — Change/Event Workloads
- change streams or equivalents
- consumer lag
- reconnect behavior
- failover behavior
## W7 — Hybrid Relational/Document
- relational filters over document sets
- joins between relational and document data
- cross-model transactions
- reporting/analytics
## W8 — Multitenancy
- many small tenants
- mixed tenant sizes
- tenant provisioning
- whale tenant
- noisy neighbours
- placement changes
- isolation tests
## W9 — Operations
- failover
- backup
- restore
- upgrade
- extension upgrade
- scaling
- disaster simulation
---
# 25. Whale-Tenant Experiment
One canonical multitenancy experiment should be designed into the architecture from the start.
Example distribution:
```text
1000 tenants total
950 small tenants
49 medium tenants
1 whale tenant consuming roughly half of traffic
```
The exact distribution should be parameterized.
Questions:
- What happens to small-tenant p99 latency?
- Can the whale be identified operationally?
- Can the whale move from T0 to T2/T3?
- How long does migration take?
- How much downtime occurs?
- Does the application connection contract change?
- What happens to backup cost?
- At what point does dedicated placement become economically sensible?
This should eventually become a signature DocStorePG benchmark.
---
# 26. Tenant Migration Architecture
Tenant migration is initially an experimental subsystem.
```mermaid
flowchart LR
S[Source Placement]
E[Export / Replication]
V[Validate]
C[Cutover]
T[Target Placement]
R[Rollback Window]
S --> E --> V --> C --> T
C --> R
```
Desired migration properties:
- tenant-scoped
- auditable
- resumable
- consistency-aware
- verifiable
- rollback-aware
- application-transparent where possible
Potential mechanisms to investigate:
- logical export/import
- PostgreSQL logical replication
- document API replication
- change streams
- dual writes
- maintenance-window cutover
- backup/restore extraction
No mechanism is canonical yet.
---
# 27. DocumentDB Kubernetes Operator Relationship
The DocumentDB Kubernetes Operator is a relevant upstream project and should be actively compared with DocStorePG.
It already uses CloudNativePG underneath and provides Kubernetes-native DocumentDB lifecycle capabilities.
DocStorePG should therefore avoid duplicating its implementation without evidence.
Initial relationship:
```text
DocumentDB Operator
|
+-- upstream reference implementation
+-- optional deployment profile
+-- research comparator
+-- source of operational lessons
DocStorePG
|
+-- broader PostgreSQL document capability research
+-- interchangeable gateways
+-- native JSONB baseline
+-- multitenancy comparison
+-- MongoDB comparison
+-- conformance framework
+-- benchmark framework
+-- hybrid relational/document research
```
If the DocumentDB Operator eventually provides the best runtime deployment path, DocStorePG should be able to adopt it rather than compete with it.
---
# 28. Failure Domains
DocStorePG should model failure domains explicitly.
| Failure | Likely scope | Expected owner |
|---|---|---|
| Gateway pod | Mongo API traffic through pod | Kubernetes / gateway |
| Gateway deployment | Mongo-compatible surface | DocStorePG deployment |
| PostgreSQL instance | instance | CloudNativePG |
| PostgreSQL primary | writes until failover | CloudNativePG |
| PostgreSQL cluster | tenant set on cluster | operations |
| PVC/storage | instance or cluster | Kubernetes/storage |
| Namespace | contained deployments | Kubernetes |
| Kubernetes node | scheduled workloads | Kubernetes |
| Kubernetes cluster | all contained placements | infrastructure |
| Tenant credential leak | tenant/security boundary | security model |
| RLS policy error | pooled tenants | DocStorePG policy |
| Extension defect | databases using extension | upstream + operations |
Dedicated tenant placement should reduce blast radius at the cost of operational density.
---
# 29. Scaling Model
DocStorePG should distinguish four fundamentally different scaling mechanisms.
## Vertical
Increase:
- CPU
- memory
- storage performance
## Read Scale
Add PostgreSQL replicas where semantics permit.
## Gateway Scale
Increase stateless gateway replicas.
## Placement Scale
Move tenants or workloads onto additional independent DocStorePG deployments.
```text
scale
|
+-----------------+----------------+
| | |
vertical gateway placement
|
+--------+--------+
| |
shared dedicated
```
Transparent horizontal write sharding is explicitly outside the initial model.
---
# 30. Repository Architecture
Proposed repository structure:
```text
doc-store-pg/
├── INTENT.md
├── ArchitectureBlueprint.md
├── ResearchProgram.md
├── BenchmarkSpecification.md
├── CompatibilityModel.md
├── MultitenancyModel.md
├── WorkloadCatalog.md
├── README.md
├── docs/
│ ├── architecture/
│ ├── decisions/
│ ├── findings/
│ └── references/
├── deploy/
│ ├── cnpg/
│ ├── documentdb/
│ ├── gateways/
│ │ ├── documentdb/
│ │ └── ferretdb/
│ └── mongodb-reference/
├── profiles/
│ ├── platform/
│ ├── engine/
│ ├── gateway/
│ ├── tenancy/
│ └── workload/
├── experiments/
│ ├── compatibility/
│ ├── performance/
│ ├── multitenancy/
│ ├── operations/
│ └── migration/
├── benchmarks/
│ ├── runner/
│ ├── workloads/
│ ├── schemas/
│ └── analysis/
├── tests/
│ ├── conformance/
│ ├── security/
│ ├── failover/
│ └── integration/
├── results/
│ └── README.md
└── scripts/
```
Generated benchmark results should be governed carefully so the repository does not become filled with large ephemeral datasets.
Machine-readable summaries belong in Git where useful; raw large datasets may require external object storage with manifests/checksums committed to the repository.
---
# 31. Initial Implementation Stages
## Stage A — Functional Baseline
Establish:
```text
Kubernetes
+ CloudNativePG
+ PostgreSQL
```
Verify normal SQL operation.
## Stage B — Document Engine
Add:
```text
DocumentDB extensions
```
Verify document operations through PostgreSQL-native interfaces.
## Stage C — Mongo-Compatible Surface
Add:
```text
DocumentDB Gateway
```
Run basic official-driver CRUD tests.
## Stage D — Alternative Gateway
Add:
```text
FerretDB
```
Run the same tests against the same backend profile.
## Stage E — MongoDB Reference
Deploy native MongoDB as M0.
Run differential CRUD/query tests.
## Stage F — Tenant Baseline
Implement T0 pooled tenancy and evaluate PostgreSQL-enforced isolation.
## Stage G — Isolation Ladder
Add T2 database-per-tenant and T3 dedicated placement.
Treat T1 schema-per-tenant as experimental and implement only if document-engine behavior supports it cleanly.
## Stage H — Benchmark Plane
Add machine-readable benchmark runs and environment manifests.
## Stage I — Operational Experiments
Test:
- failover
- restart
- backup
- restore
- upgrade
- noisy neighbour
- tenant movement
---
# 32. Initial Architecture Decisions
The following decisions are provisional but form the starting baseline.
### AD-001 — CloudNativePG is the PostgreSQL operator
**Decision:** Use CloudNativePG rather than introducing a custom PostgreSQL lifecycle implementation.
**Reason:** PostgreSQL lifecycle and HA are not DocStorePG's differentiated problem.
### AD-002 — DocumentDB is the initial document engine
**Decision:** Use DocumentDB extensions as the first BSON/document compatibility implementation.
**Reason:** It already implements document semantics on PostgreSQL and exposes a MongoDB-compatible gateway architecture.
### AD-003 — Gateway implementation remains swappable
**Decision:** Support DocumentDB Gateway first; preserve FerretDB as an alternative profile.
**Reason:** This allows protocol-layer effects to be isolated experimentally.
### AD-004 — PostgreSQL access remains first-class
**Decision:** Do not hide SQL/PostgreSQL interfaces behind the document API.
**Reason:** Hybrid relational/document capability is a core research hypothesis.
### AD-005 — Multitenancy has explicit placement levels
**Decision:** Use T0T3 as stable architectural vocabulary.
**Reason:** Isolation, cost, and scaling cannot be meaningfully represented by a single "multi-tenant" mode.
### AD-006 — No custom DocStorePG operator initially
**Decision:** Start with manifests/profiles and existing operators.
**Reason:** Operator behavior should only be built once recurring control-plane requirements are empirically understood.
### AD-007 — No claim of transparent write sharding
**Decision:** Treat MongoDB sharding as a distinct comparison point rather than something DocStorePG already provides.
**Reason:** CloudNativePG HA and MongoDB sharding solve different problems.
### AD-008 — Benchmarks are architecture
**Decision:** Reproducible benchmark and conformance hooks are part of the system design from the beginning.
**Reason:** Long-term architecture choices must remain evidence-driven.
---
# 33. Architecture Questions to Resolve Through Research
The blueprint intentionally leaves these open:
1. How complete is DocumentDB's real MongoDB semantic compatibility?
2. Does DocumentDB Gateway or FerretDB provide the better compatibility/performance trade-off?
3. How should Mongo identities map to PostgreSQL identities?
4. Can PostgreSQL RLS reliably enforce pooled tenant isolation through the Mongo-compatible surface?
5. What tenant count is practical for database-per-tenant within one CNPG cluster?
6. Is schema-per-tenant useful with DocumentDB or merely theoretical?
7. How much gateway overhead exists relative to direct document access?
8. How much document-engine overhead exists relative to native JSONB?
9. Where does native MongoDB outperform the PostgreSQL-backed architecture?
10. How do both architectures behave with a whale tenant?
11. What is the operational cost per tenant under T0, T2, and T3?
12. How should tenant migration work?
13. Can a stable logical endpoint survive tenant placement changes?
14. Which MongoDB read/write/session semantics can safely map to CNPG primary/replica topology?
15. What backup granularity is achievable for each tenant model?
16. How should extension versions be upgraded independently from PostgreSQL?
17. When does an existing distributed PostgreSQL technology become preferable to DocStorePG placement routing?
18. When should a workload simply remain on native MongoDB?
These questions should seed `ResearchProgram.md`.
---
# 34. Target Architecture
The long-term target, if supported by evidence, is:
```mermaid
flowchart TB
subgraph Applications
M[MongoDB clients]
S[SQL clients]
end
EP[Stable DocStorePG Endpoint]
TC[Tenant / Placement Control]
subgraph Shared["Shared Placement"]
SP[CNPG + DocumentDB]
end
subgraph DB["Database-Isolated Placement"]
DP[CNPG + Tenant Databases]
end
subgraph Dedicated["Dedicated Placements"]
D1[CNPG Tenant A]
D2[CNPG Tenant B]
end
OBS[Observability]
BENCH[Conformance & Benchmark Plane]
M --> EP
S --> EP
EP --> TC
TC --> SP
TC --> DP
TC --> D1
TC --> D2
SP --> OBS
DP --> OBS
D1 --> OBS
D2 --> OBS
BENCH --> EP
BENCH --> OBS
```
The important feature is not that all boxes necessarily become custom DocStorePG software.
The important feature is that the platform can express and test:
```text
interface
+ document semantics
+ tenant identity
+ placement
+ isolation
+ PostgreSQL capability
+ operations
+ evidence
```
as separable concerns.
---
# 35. Architectural North Star
`doc-store-pg` should aim to make this statement testable:
> A document store can be an operationally native PostgreSQL capability whose API, compatibility, tenant placement, and isolation level can evolve independently from the applications that use it.
The architecture succeeds if it allows the project to discover where that statement is true, where it is false, and where MongoDB or another architecture remains the better engineering choice.
The purpose is not to prove PostgreSQL wins.
The purpose is to create a system in which the trade-offs become measurable.
---
# 36. References and Upstream Baseline
The following upstream sources establish the initial technical baseline for this blueprint. Versions and capabilities should be revalidated when experiments are run.
1. **CloudNativePG — Image Volume Extensions**
https://cloudnative-pg.io/documentation/current/imagevolume_extensions/
2. **CloudNativePG — Operator Capability Levels**
https://cloudnative-pg.io/docs/current/operator_capability_levels/
3. **CloudNativePG — Declarative Database Management**
https://cloudnative-pg.io/docs/devel/declarative_database_management/
4. **CloudNativePG 1.30 Release**
https://cloudnative-pg.io/releases/cloudnative-pg-1-30.0-released/
5. **DocumentDB — Getting Started / Architecture Components**
https://documentdb.io/docs/getting-started
6. **DocumentDB — PostgreSQL API / Gateway**
https://documentdb.io/docs/postgres-api
7. **DocumentDB Kubernetes Operator**
https://documentdb.io/kubernetes-operator
8. **DocumentDB Kubernetes Operator — API Reference**
https://documentdb.io/documentdb-kubernetes-operator/latest/preview/api-reference/
9. **FerretDB — Introduction**
https://docs.ferretdb.io/
10. **FerretDB — Migration to v2 / DocumentDB Backend**
https://docs.ferretdb.io/migration/migrating-from-v1/
11. **PostgreSQL — Row Security Policies**
https://www.postgresql.org/docs/current/ddl-rowsecurity.html
12. **MongoDB — Multi-Tenant Architecture**
https://www.mongodb.com/docs/atlas/build-multi-tenant-arch/
13. **MongoDB — Sharding**
https://www.mongodb.com/docs/manual/sharding/
14. **MongoDB — Scaling Strategies / Collection Placement**
https://www.mongodb.com/docs/manual/core/sharding-scaling-strategies/
15. **MongoDB — Manage Unsharded Collections**
https://www.mongodb.com/docs/manual/core/sharding-manage-unsharded-collections/