Limitations & roadmap (read before production)

July 18, 2026 · View on GitHub

UniSchema is v0.4.2 — strong for pilots and webhook normalization proofs; not yet "drop in and forget." This page states what works today and what teams ask about before trusting production donor data.

What works well today

  • Eight built-in vendors → ConstituentEvent with HMAC verification
  • Async ingest with crash recovery
  • Local or S3 egress push
  • Visual mapping canvas for field overrides + normalizedMetadata
  • PhilanthroPy integrationphilanthropy-integration.md
  • SQLite default or optional Postgres (postgres.md)
  • Docker Compose + single-URL bundled UI
  • 15-minute demo (npm run demo:multi)

Vendor maturity tiers

TierVendorsStatus
Tier 1GiveCampus, CventProduction-tested fixtures, primary support
Tier 2iModulesReference vendor #3 implementation
Tier 3Blackbaud, NPSP, Slate, Ellucian, CiviCRMCommunity mappers — verify with your real payloads

See vendor registry for the canonical list.

Honest limitations (v0.4.2)

Not every advancement vendor is built-in

Niche CRMs still require the 6-file vendor checklist. Tier 3 vendors (including Ellucian) — verify payloads against your instance before production.

Fixed master schema

Core fields (constituentEmail, eventType, sourceSystem, etc.) are opinionated for cross-vendor consistency.

  • Good: one downstream model for analytics and ML
  • Bad: if your org's canonical constituent model differs significantly

Use normalizedMetadata for org-specific fields. Changing core fields requires schema + pipeline coordination (schema-governance.md).

Three event types only

EVENT_REGISTRATION, DONATION, EMAIL_CLICK

Email opens, volunteer shifts, membership renewals, etc. must map to the nearest type or wait for enum extensions via RFC — see schema-governance.md.

Scale characteristics

Pilot (SQLite, single instance):

  • Single-instance deploy
  • Thousands to low millions of rows with modest write rates
  • Default ~120 req/min/IP rate limit

Production (Postgres, optional Redis):

Not fine for (today):

  • Multi-region active-active
  • Very high burst rates without load testing

Many environment variables

Production requires webhook secrets, egress config, mapping sync token, etc. See operator-guide.md. Compose files (docker-compose.yml for pilots vs docker-compose.prod.yml) reduce guesswork.

Drift agent is experimental

The LLM drift runner (agents/drift_runner/) is human-in-the-loop assistive tooling:

It doesIt does not
Capture failed payloads in a drift queueAuto-deploy mapper fixes
Propose patches under agents/output/Self-heal production without review
Generate Vitest fixture scaffoldingReplace your change management

Do not enable unsupervised agent loops against production. See ai-agent-loop.md and agents/README.md.

No managed SaaS (yet)

Self-host Node + secrets + S3 (+ optionally Airflow) is still required. Cloud templates: deploy/README.md.


Scale & database

Current architecture

Node process(es)
  └── SQLite (default) or Postgres (DATABASE_URL)
  └── Optional Redis rate limit (REDIS_URL)
  └── In-memory S3 batch buffer (per instance)
  └── Optional pg-boss ingest queue (when DATABASE_URL set)

Default rate limit: 120 requests / minute / client IP (WEBHOOK_RATE_LIMIT_MAX). Tune for your vendor's burst pattern.

Async ingest: Webhooks return 202 immediately; mapping runs in background. Throughput is adequate for typical advancement webhook volumes on one instance; run npm run benchmark before peak giving day.

Before high-volume production

Questionv0.2.0 answerPlanned direction
Postgres instead of SQLite?Supported via DATABASE_URLDocumented migration path
Horizontal scaling (2+ instances)?Postgres + optional RedisMulti-instance deploy guide
Webhook volume limits?Benchmarked — see benchmarks.mdPer-release numbers
Multi-region?Single regionOut of scope for v0.2

Recommendation: Run a pilot on SQLite + S3 egress. Measure peak webhooks/minute during a giving period. If you need >1 instance, use Postgres + Redis per deploy/README.md.

Data durability

  • Ingest state: SQLite or Postgres (webhook_ingestions, constituent_events)
  • Egress: S3 (durable) or local disk (volume backups required)
  • Recovery workers re-process stale pending ingestions and egress on startup

Roadmap themes (not committed dates)

  1. Adoption — GHCR releases, compose profiles, PhilanthroPy bridge ✅ v0.3
  2. Vendors — promote Tier 3 mappers to Tier 1 as real payload fixtures are contributed
  3. Scale — Redis rate limit, pg-boss queue, published benchmarks ✅ in progress
  4. Product — metadata canvas, import mapping, drift UI actions ✅ in progress
  5. Trust (v1.0) — OIDC admin auth, mapping audit log, compliance docs

Contributions welcome — especially vendor mappers with real payload fixtures and tests.