Legacy industrial historians were architected in the 1980s around an assumption that stopped being true twenty years ago: disk storage was scarce and expensive.
To survive on 1980s spinning media, proprietary systems like the OSIsoft / AVEVA PI System introduced two compromises that regulated biopharma plants have been paying for ever since:
- Lossy “Swinging Door” (
CompDev) archive compression, which discards raw sensor readings and replaces them with straight-line approximations—risking blunted UV280 chromatography peaks on a purification skid or concealed thermal transients during GMP batch review. - Per-tag and per-seat licensing tiers paired with fragile Windows DCOM plumbing, which forces automation teams to ration which shop-floor parameters get archived and locks historical batch data inside proprietary binary
.datfiles.
On the other side of the aisle, generic open-source time-series stacks (vanilla InfluxDB, Prometheus, or raw TimescaleDB) fail the moment an FDA or EMA inspector asks for 21 CFR Part 11 §11.10(e) Write-Once-Read-Many (WORM) audit trails, §11.200 dual-challenge electronic signatures, ISA-95 hierarchical asset context, ISA-88 batch and excursion Event Frames, OPC signal quality (quality >= 192) filtering, and discrete (LOCF) versus continuous (LINEAR) interpolation.
We built GxPHistorian (github.com/saram-io/gxp-historian) to close that gap. It is an MIT-licensed, 4-Pillar open-source industrial time-series historian and asset framework engineered from the database kernel up for 21 CFR Part 11, EU GMP Annex 11, and ISPE GAMP 5 (Second Edition).
1. The 4-Pillar Architecture: Separating Immutable Telemetry from Mutable Control
A regulated industrial historian has to solve two fundamentally opposite database workloads at the same time:
- High-frequency append-only telemetry (
1 Hzto10 Hzacross tens of thousands of tags), which must be ingested without lock contention, compressed losslessly, and aggregated over decades of batch history. - Transactional relational control state (ISA-95 asset trees, tag engineering catalogs, ISA-88 Event Frame state transitions, and 21 CFR Part 11 WORM audit logs), which requires strict ACID transactions, foreign-key integrity, and kernel-level triggers.
Forcing high-frequency telemetry into a row-oriented relational engine creates B-tree index bloat and VACUUM stalls. Conversely, storing mutable Event Frames and Part 11 audit trails inside a columnar OLAP engine triggers expensive ALTER TABLE ... UPDATE/DELETE part rewrites.
GxPHistorian decouples these workloads into four specialized pillars bridged in real time via an in-memory ClickHouse FLAT dictionary:
┌────────────────────────────────────────────────────────────────────────────┐
│ GxPHistorian 4-Pillar Architecture │
├────────────────────────────────────────────────────────────────────────────┤
│ │
│ PILLAR 1: Multi-Protocol Edge Collector (edge-collector) │
│ ┌────────────────────────────────────┐ ┌─────────────────────────────┐ │
│ │ OPC UA (:4840), S7comm (:102), │ │ Stage 1 Exception Deadband │ │
│ │ BACnet/IP (:47808 COV) & MS/TP, │──▶│ Filter (ExcDev / ExcMax) │ │
│ │ Modbus TCP/RTU, HART, RS-232, │ │ + 1,000,000-Sample Disk WAL │ │
│ │ Zero-DCOM Windows OPC DA, Watchdir │ │ (/var/lib/telegraf/buffer) │ │
│ └────────────────────────────────────┘ └──────────────┬──────────────┘ │
│ │ │
│ HTTP JSONEachRow (:8125) │
│ ▼ │
│ PILLAR 2: Immutable Telemetry Archive PILLAR 3: Part 11 Control Plane │
│ (clickhouse-archive — ClickHouse 24.8) (postgres-control + FastAPI) │
│ ┌────────────────────────────────────┐ ┌─────────────────────────────┐ │
│ │ pi_historian.sensor_data │ │ PostgreSQL 16 (ltree, │ │
│ │ MergeTree partitioned by YYYYMM │ │ btree_gist, pgcrypto) │ │
│ │ Codecs: Delta + DoubleDelta + │ │ • ISA-95 Asset Hierarchy │ │
│ │ Gorilla + T64 + ZSTD(1) │ │ • Tag Catalog & Limits │ │
│ │ (1.5–2.5 bytes/sample, 100% raw) │ │ • ISA-88 Event Frames │ │
│ ├────────────────────────────────────┤ │ • PL/pgSQL WORM Triggers │ │
│ │ pi_historian.sensor_rollup_1m │ │ • SHA-256 Audit Hash Chain │ │
│ │ AggregatingMergeTree │ │ • §11.200 HMAC E-Signatures │ │
│ │ Strictly WHERE quality >= 192 │ ├─────────────────────────────┤ │
│ ├────────────────────────────────────┤ │ FastAPI + Pydantic AI + MCP │ │
│ │ pi_historian.pg_asset_tags │◀──│ v_clickhouse_tag_dict sync │ │
│ │ In-Memory FLAT Dictionary (5–15s) │ │ LTTB, DataLink & AI CoPilot │ │
│ └─────────────────┬──────────────────┘ └──────────────┬──────────────┘ │
│ │ │ │
│ └──────────────────┬──────────────────┘ │
│ ▼ │
│ PILLAR 4: Operator HMI, Excel DataLink & Enterprise Lakehouse │
│ ┌──────────────────────┐ ┌────────────────────────┐ ┌──────────────────┐ │
│ │ Grafana OSS 11.2 HMI │ │ Excel DataLink Client │ │ Zero-ETL Parquet │ │
│ │ Asset-Relative LTTB │ │ xlwings UDFs + Native │ │ PyArrow Snappy │ │
│ │ Trends + EF Overlays │ │ Power Query CSV Stream │ │ + S3 WORM Tier │ │
│ └──────────────────────┘ └────────────────────────┘ └──────────────────┘ │
└────────────────────────────────────────────────────────────────────────────┘
Container & Port Matrix
All five core services launch via a single orchestrated docker-compose.yml stack with deterministic healthchecks:
| Container Name | Architectural Role | Internal Port | Host Port (.env) |
Core Technology Stack |
|---|---|---|---|---|
edge-collector |
Pillar 1: Multi-Protocol Collector, Stage 1 Deadband & Disk WAL | 8080 |
8080 |
InfluxData Telegraf 1.32 Alpine + Python 3.12 |
clickhouse-archive |
Pillar 2: Lossless Time-Series Archive & 1-Minute Rollup Engine | 8123 / 9000 |
8125 / 9005 |
ClickHouse Server 24.8 LTS (Apache-2.0) |
postgres-control |
Pillar 3: ISA-95 Asset Hierarchy & 21 CFR Part 11 WORM Audit Log | 5432 |
5435 |
PostgreSQL 16 (ltree, btree_gist, pgcrypto) |
historian-api |
Pillar 3: GxP REST API, Event Frame Engine, DataLink & AI/MCP | 8000 |
8020 |
FastAPI, Psycopg 3, ClickHouse Connect, PyArrow, Pydantic AI, FastMCP |
grafana-vision |
Pillar 4: Pre-Provisioned Bioreactor & Cleanroom Operator HMI | 3000 |
3020 |
Grafana OSS 11.2 + ClickHouse & PostgreSQL Datasources |
2. 1-to-1 Parity with the OSIsoft / AVEVA PI System
Migrating off a legacy historian fails if process engineers lose their Excel batch reports or operators lose their asset-relative trend displays. Every subsystem in GxPHistorian maps directly to its familiar OSIsoft / AVEVA PI System counterpart:
| Legacy OSIsoft / AVEVA PI Component | GxPHistorian Open-Source Equivalent | Key Technical & Regulatory Capabilities |
|---|---|---|
PI Data Archive (Swinging Door CompDev) |
ClickHouse 24.8 LTS (pi_historian.sensor_data) |
100% mathematically lossless Delta, DoubleDelta, Gorilla & T64 + ZSTD(1) compression (1.5–2.5 B/sample) + real-time 1m AggregatingMergeTree rollups (WHERE quality >= 192). |
| PI Asset Framework (PI AF) | PostgreSQL 16 ltree + ClickHouse FLAT Dictionary |
ISA-95 Enterprise.Site.Area.Unit paths indexed via GiST and synchronized into ClickHouse RAM (pg_asset_tags) every 5–15 seconds for O(1) metadata enrichment. |
| PI Event Frames (EF) | PostgreSQL event_frames + FastAPI State Machine |
Automated ISA-88 batch & excursion capture (peak_val, avg_val, min_val, sample_count over quality >= 192) with §11.200 dual-challenge HMAC-SHA256 electronic signatures. |
| PI Interface Node & PI Buffer Subsystem | Telegraf 1.32 Disk WAL + Python Edge Workers | In-memory Stage 1 Exception/Deadband filtering (ExcDev & ExcMax) + 1,000,000-metric disk store-and-forward WAL (/var/lib/telegraf/buffer) across 10 industrial protocols. |
PI Vision (PlotValues Trends & Overlays) |
Grafana OSS 11.2 + ClickHouse LTTB | Asset-relative (${asset_path}) operator HMI with native largestTriangleThreeBuckets peak preservation, Event Frame shaded bands, and live Part 11 WORM audit table. |
PI DataLink (Excel PISampDat / PIAdvCalcDat) |
FastAPI DataLink CSV/JSON + xlwings UDFs |
Drop-in =GXPHISTORIAN_SAMPLED(), =GXPHISTORIAN_PLOT_VALUES(), and =GXPHISTORIAN_EVENT_SUMMARY() Excel functions plus zero-macro Power Query CSV streams enforcing LINEAR vs. LOCF interpolation. |
| PI Integrator for Business Analytics | FastAPI + PyArrow Zero-ETL Exporter | Single-call POST /api/v1/lakehouse/export-parquet generating Snappy-compressed Apache Parquet files enriched with ISA-95 asset paths and engineering units. |
| AVEVA Industrial AI Assistant / PI Web API | Pydantic AI Co-Pilot & gxphistorian-mcp Server |
Typed ISA-88 Excursion Investigator (DeviationInvestigationBrief, WHERE quality >= 192), Part 11 human-in-the-loop ApprovalRequired tag provisioning, and 6-tool FastMCP server. |
3. The Compression Math: Why Lossy Swinging Door Is Obsolete
In a legacy PI System, data reduction happens in two stages:
- Stage 1 (Exception Reporting at the Interface Node): Suppresses stationary ADC electrical jitter within an exception deadband (
ExcDev) until a meaningful change occurs or the heartbeat timer (ExcMax) expires. - Stage 2 (Swinging Door Compression at the Archive): Discards actual emitted points that fall within a sloped parallelogram (
CompDev), storing only inflection points.
Stage 1 makes physical sense—recording 24-bit ADC thermal noise when a bioreactor hold temperature sits at 37.00°C wastes network bandwidth. Stage 2 (CompDev), however, permanently alters the original measurement record. If CompDev is misconfigured on a tangential flow filtration (TFF) transmembrane pressure sensor or a chromatography UV280 detector, sharp transient spikes are smoothed away before they ever hit disk. Under ALCOA+ Original and Accurate record principles, throwing away emitted primary data to save a few bytes is an unnecessary regulatory risk.
GxPHistorian retains Stage 1 Exception Deadband filtering (ExcDev / ExcMax) at the Purdue Level 2.5 edge (edge-collector)—and sets exc_dev = 0.0 for at-line PAT analyzers so every discrete assay is captured—while replacing Stage 2 with 100% mathematically lossless columnar codecs in ClickHouse (init-clickhouse/01_telemetry_core.sql):
CREATE TABLE IF NOT EXISTS pi_historian.sensor_data
(
tag_id UInt32 CODEC(Delta, ZSTD(1)),
ts DateTime64(3, 'UTC') CODEC(DoubleDelta, ZSTD(1)),
val Float64 CODEC(Gorilla, ZSTD(1)),
str_val LowCardinality(String) DEFAULT '' CODEC(ZSTD(1)),
quality UInt8 DEFAULT 192 CODEC(T64, ZSTD(1)),
status_code UInt16 DEFAULT 0 CODEC(T64, ZSTD(1))
)
ENGINE = MergeTree()
PARTITION BY toYYYYMM(ts)
ORDER BY (tag_id, ts);
Because rows are physically sorted on disk by (tag_id, ts):
DoubleDeltaonts(DateTime64(3, 'UTC')): At regular1 Hzpolling intervals, the second derivative of the timestamp is0, compressing an 8-byte millisecond timestamp to 1–2 bits beforeZSTD(1).GorillaXOR onval(Float64): Facebook’s Gorilla XOR floating-point codec XORs consecutive IEEE 754 values for the sametag_id, storing only the changed mantissa bits.T64bit-transposition onqualityandstatus_code: Since OPC Good quality (192) is constant across >99.9% of samples, bit-transposition plusZSTD(1)reduces the quality column to near-zero overhead.
An uncompressed 25-byte telemetry row plus its 1-minute AggregatingMergeTree rollup state compresses to B_eff ≈ 1.5 to 2.5 bytes per sample:
Annual Disk per Tag (at 1 Hz) = 86,400 samples/day × 365.25 days × B_eff × (1 - R_deadband)
Even for a 25,000-tag commercial GMP facility, 10 years of online hot NVMe storage is remarkably small:
| Operating Scenario | Effective Sample Rate (1 - R_deadband) |
Bytes / Tag / Day | Annual Storage / Tag | 10-Year Hot Storage (25,000 Tags) |
|---|---|---|---|---|
Worst-Case Continuous (exc_dev = 0, 100% 1 Hz) |
1.00 Hz (0% suppression) |
216 KB/day |
78.9 MB/yr |
19.7 TB |
Conservative GMP Bioprocess Mix (50% suppression) |
0.50 Hz average |
108 KB/day |
39.5 MB/yr |
9.86 TB |
Typical GMP Plant Mix (70% deadband suppression) |
0.30 Hz average |
64.8 KB/day |
23.7 MB/yr |
5.92 TB |
After 10 years on local enterprise NVMe RAID-1, ClickHouse’s native multi-volume TTL ts + INTERVAL 10 YEAR TO VOLUME 'cold_worm_s3' zero-copy tiering moves aged partitions to 15-year S3 / MinIO Object Lock (Compliance Mode) storage to satisfy FDA 21 CFR 211.180 and EU GMP Chapter 4 retention rules.
4. Database-Kernel 21 CFR Part 11 WORM & Cryptographic Hash Chaining
FDA and EMA data integrity auditors no longer accept “trust the web application” as a control for electronic batch records. If an audit log is written only by Python or Node.js middleware, anyone with a database credential—or a bug in an ORM migration—can mutate a tag limit or delete an audit row without leaving a trace.
GxPHistorian enforces 21 CFR Part 11 and EU GMP Annex 11 directly inside the PostgreSQL 16 database kernel (init-postgres/01_control_plane_part11.sql):
1. Mandatory Session Attribution (21 CFR §11.10(e))
Every INSERT, UPDATE, or DELETE on asset_templates, assets, tags, and event_frames is intercepted by the PL/pgSQL trigger function fn_enforce_part11_audit(). Before executing any DML statement, the transaction must bind app.actor_id and app.change_reason via SET LOCAL (populated from X-Actor-Id and X-Change-Reason HTTP headers on historian-api). Any unattributed SQL mutation immediately aborts the transaction:
-- Enforce mandatory 21 CFR Part 11 attribution context
v_actor := NULLIF(current_setting('app.actor_id', true), '');
v_reason := NULLIF(current_setting('app.change_reason', true), '');
IF v_actor IS NULL OR v_reason IS NULL THEN
RAISE EXCEPTION '21 CFR Part 11 Violation: app.actor_id and app.change_reason are mandatory';
END IF;
2. Unconditional WORM Audit Triggers
The part11_audit_log table attaches both row-level and statement-level triggers (trg_worm_part11_audit_log_row and trg_worm_part11_audit_log_stmt) executing fn_prevent_audit_tampering(). Any UPDATE, DELETE, or TRUNCATE against part11_audit_log unconditionally raises 21 CFR Part 11 WORM Violation: Audit trail records are immutable—blocking tampering even by PostgreSQL superusers.
3. Cryptographic SHA-256 Hash Chaining (ALCOA+ Original & Enduring)
Every audit row locks the table in EXCLUSIVE MODE to serialize chain order and computes a pgcrypto SHA-256 digest linking the prior row’s hash starting from GENESIS_0000000000000000:
row_hash = SHA256(prev_hash || recorded_at || actor_id || operation || coalesce(new_payload, ''))
At any point during an inspection, QA can verify end-to-end cryptographic integrity from genesis via GET /api/v1/audit-trail/verify:
{
"chain_valid": true,
"verified_records": 220,
"genesis_anchor": "GENESIS_0000000000000000",
"broken_links": []
}
4. Dual-Challenge Electronic Signatures (§11.50, §11.70, §11.200)
Signing an ISA-88 Event Frame (POST /api/v1/event-frames/{event_id}/sign) requires a live dual-component challenge (user_id + password) verified against pgcrypto bcrypt hashes in PostgreSQL users. Upon verification, the control plane computes a non-repudiable HMAC-SHA256 signature digest over (event_id, user_id, signature_meaning, signed_at), binds the signature to the Event Frame, and records the execution in part11_audit_log.
5. Signal Quality Discipline (quality >= 192) and Step vs. Continuous Interpolation
Two subtle data-integrity bugs routinely corrupt custom historian implementations in biopharma:
Bug 1: Bad-Quality Sensor Faults Corrupting Batch Rollups
When a Pt100 RTD probe experiences a wire break or a pH probe is pulled during Clean-in-Place (CIP), PLCs frequently transmit sentinel fault values (-999.0 or 9999.0) tagged with OPC quality 0 (Bad) or 64 (Uncertain).
- If you discard
quality < 192before ingestion, maintenance engineers lose the diagnostic evidence of when the wire broke. - If you include
quality < 192in your rollups, a single 1-second9999.0fault ruins the batch’s 1-minute average and triggers false excursion KPIs.
GxPHistorian archives all raw diagnostic states (192 = Good, 64 = Uncertain, 0 = Bad) in pi_historian.sensor_data, while strictly enforcing WHERE quality >= 192 across the 1-minute AggregatingMergeTree materialized view (mv_sensor_rollup_1m), ClickHouse largestTriangleThreeBuckets (LTTB) trend queries, Event Frame KPI calculations, and Excel DataLink exports.
Bug 2: Linear Interpolation of Discrete Equipment States
Continuous analog measurements (BR201_TEMP_PV, BR201_PH_PV, where is_step_tag = false) change smoothly over time and should be interpolated linearly (LINEAR) between archived timestamps. Discrete integer state tags (BR201_AGIT_STATE where 0 = Off, 1 = Low, 2 = High, or ISA-88 phase state tags where is_step_tag = true) jump instantaneously. Linearly interpolating a discrete tag between 1 and 2 synthesizes a non-existent state of 1.5.
GxPHistorian stores is_step_tag in PostgreSQL tags, syncs it into ClickHouse RAM (pi_historian.pg_asset_tags), and automatically dispatches:
- Continuous tags (
is_step_tag = false): ClickHouse time-weighted linear interpolation (WITH FILL STEP ... INTERPOLATE). - Discrete step tags (
is_step_tag = true): Last Observation Carried Forward (LOCF_STEP) so integer equipment states never produce fractional artifacts in Grafana or Excel DataLink (=GXPHISTORIAN_SAMPLED()).
6. Deterministic AI Orchestration: Pydantic AI Co-Pilot & gxphistorian-mcp
Allowing a large language model to calculate time-series averages, interpolate timestamps in its context window, or execute electronic signatures would violate both GAMP 5 and ALCOA+ Accurate principles.
GxPHistorian implements an explicit architectural boundary in app/gxp_ai_agent.py (built on Pydantic AI) and app/mcp_server.py (built on FastMCP):
Core GxP AI Rule: AI proposes, queries, and correlates; deterministic ClickHouse and PostgreSQL execute, filter (
WHERE quality >= 192), interpolate (LINEARvs.LOCF_STEP), and audit (SHA-256WORM chain).
1. Automated ISA-88 Excursion Pre-Investigation (gxp_deviation_investigator_agent)
When an Event Frame opens—for example, BR201_TEMP_PV_High_Limit_Excursion on BioCorp.Fremont.USP.Bioreactor_201—the investigator agent assembles a strictly typed DeviationInvestigationBrief Pydantic model (POST /api/v1/ai/event-frames/{event_id}/investigate):
- Sibling Tag Correlation: Queries deterministic ClickHouse
min_val,avg_val,max_val,good_sample_count(quality >= 192), andbad_quality_sample_count(quality < 192) across all tags attached to the same ISA-95 asset (BR201_TEMP_PV,BR201_PH_PV,BR201_AGIT_STATE). - Capabilities on Demand (
defer_loading=True): Dynamically loads thepart11-forensicscapability to verify the PostgreSQL SHA-256 audit hash chain (verify_part11_hash_chain), inspect recent attributed changes (part11_audit_log), and rundiagnose_opc_signal_qualityto classify whether the event is a truecritical_process_excursion, asensor_or_signal_fault(quality < 192), or an intentionalsetpoint_or_recipe_transition.
2. Human-in-the-Loop Tag Onboarding (gxp_copilot_agent + ApprovalRequired)
When an automation engineer asks to onboard a new instrument (POST /api/v1/ai/copilot/propose-tag), gxp_copilot_agent loads the brownfield-onboarding capability (defer_loading=True), searches the 35+ biopharma equipment playbooks, validates engineering limits via args_validator (triggering ModelRetry if low_limit >= high_limit or if a step tag specifies a non-zero deadband), and raises Pydantic AI’s ApprovalRequired (DeferredToolRequests).
No database write occurs until a human engineer reviews the staged BrownfieldOnboardingPlan and commits it with explicit X-Actor-Id and X-Change-Reason headers. Furthermore, AI agents have zero tool access to POST /api/v1/event-frames/{event_id}/sign—electronic signatures remain strictly human-only under 21 CFR §11.200.
3. Model Context Protocol Server (gxphistorian-mcp)
For external agent ecosystems (Claude Desktop, Cursor, Antigravity, or GxPChat), app/mcp_server.py exposes six read-only deterministic tools and three URI resources:
mcp_browse_assets— Browse the ISA-95ltreeasset hierarchy and tag catalog.mcp_get_lttb_plot_values— Fetch peak-preserving ClickHouse LTTB downsampled trends (WHERE quality >= 192).mcp_get_sampled_values— Fetch interpolated time-series (LINEARvs.LOCF_STEP).mcp_list_event_frames— Query ISA-88 batch and excursion Event Frames and §11.200 signature status.mcp_verify_part11_audit_chain— Execute live SHA-256 WORM hash-chain verification fromGENESIS.mcp_investigate_event_frame— Generate a deterministicDeviationInvestigationBrieffor any Event Frame UUID.
7. 35+ Biopharma Equipment Playbooks & The 8-Document GAMP 5 Validation Binder
Software alone does not qualify a GMP plant. Two field-engineering deliverables ship directly inside the repository and on gxphistorian.com:
Visual Field-Engineering Playbooks for 35+ GMP Instruments
The documentation portal (gxphistorian.com/docs) provides step-by-step physical pinouts (RJ45 T568B, M12 D/X/A-Coded, DB9 RS-232/MPI, Phoenix RS-485, 4–20 mA HART), gateway part numbers (Moxa NPort, Advantech ADAM, LOYTEC BACnet, Helmholz S7), HMI click-paths, and copy-paste tag provisioning commands across:
- Single-Use & Stainless USP Bioreactors: Cytiva Xcellerex™ XDR-50 to XDR-2000 (Figurate™ Automation / Emerson DeltaV™ / Rockwell PlantPAx®), Sartorius Biostat® STR & Ambr® 15/250, Thermo HyPerforma™ S.U.B., Eppendorf BioFlo® / DASGIP®.
- Downstream Purification (Chromatography & TFF): Cytiva ÄKTA process™ / ready™ / readyflux™ (UNICORN™ 7 OPC UA/DA with LTTB UV280 peak preservation), Sartorius Sartoflow®, MilliporeSigma Mobius® / Cogent®.
- At-Line PAT & In-Line Spectroscopy: Nova BioProfile® FLEX2, Beckman Vi-CELL™ BLU, Roche Cedex® Bio HT, Endress+Hauser Kaiser Raman Rxn2/4 (
exc_dev = 0), Hamilton Arc® intelligent probes. - Cell & Gene Therapy (CAR-T) & mRNA-LNP: Miltenyi CliniMACS Prodigy®, Cytiva Sefia™ & Sepax™ C-Pro, Precision NanoSystems NanoAssemblr™, Planer Kryo 560 Controlled-Rate Freezers (
COI_IDEvent Frames). - Aseptic Fill-Finish, Lyophilization, EMS & QC Serial: SP Scientific / Telstar freeze dryers, SKAN isolators, PMS LasAir® III particle counters, Veolia Sievers® M9 TOC, BINDER stability chambers (ClickHouse Mean Kinetic Temperature SQL), Fedegari / Getinge autoclaves (
F₀lethality SQL), and Mettler Toledo XPR / Sartorius Cubis® II balances via RS-232 MT-SICS and SHA-256 watch-folders (replacing OSIsoft PI UFL).
Turnkey 8-Document GAMP 5 & FDA CSA Validation Binder
Every release includes an executable pytest Installation and Operational Qualification (IQ/OQ) suite (17/17 automated checks covering URS-001 through URS-017) that writes timestamped cryptographic test evidence to oq_execution_results.json and compiles a print-ready 8-Document Commercial GMP Validation Binder (inspect the live HTML binder here):
VMP-GXPHISTORIAN-2026-001— Validation Master Plan (GAMP 5 2nd Ed. & FDA CSA lifecycle).URS-GXPHISTORIAN-2026-002— User Requirements Specification (URS-001toURS-017).FDS-GXPHISTORIAN-2026-003— Functional & Design Specification (4-Pillar schemas, codecs, and triggers).FRA-GXPHISTORIAN-2026-004— FDA CSA Functional Risk Assessment.SOUP-GXPHISTORIAN-2026-005— SOUP / OSS Vendor Qualification Dossier (pinned@sha256container image digests).IQOQ-GXPHISTORIAN-2026-006— Executed IQ/OQ Verification Report (17/17 Passed).RTM-GXPHISTORIAN-2026-007— Bidirectional Requirements Traceability Matrix (URS ↔ FDS ↔ FRA ↔ IQ/OQ).VSR-GXPHISTORIAN-2026-008— Validation Summary Report & QA Release Sign-Off.
8. Getting Started in 60 Seconds
You can launch the entire 5-service GxP stack—complete with a deterministic multi-protocol biopharma plant simulator (BioCorp.Fremont.USP.Bioreactor_201 and BioCorp.Fremont.Cleanroom.Suite_A), ClickHouse 24.8 LTS, PostgreSQL 16 WORM triggers, FastAPI control plane, and pre-provisioned Grafana Vision HMI—in three commands:
git clone https://github.com/saram-io/gxp-historian.git
cd gxp-historian
# 1. Launch all 5 GxP services (Edge WAL, ClickHouse, PG16, FastAPI, Grafana)
cp .env.example .env && docker compose up -d --build
# 2. Verify cryptographic SHA-256 WORM audit hash chain from GENESIS
curl -s http://localhost:8020/api/v1/audit-trail/verify | jq .
# 3. Execute the 17-test GAMP 5 / FDA CSA IQ & OQ qualification suite
.venv/bin/pytest -v
Explore GxPHistorian
- Official Website: gxphistorian.com
- Documentation & 35+ Biopharma Guides: gxphistorian.com/docs
- Executed GMP Validation Binder: gxphistorian.com/binder/COMPLETE_GMP_VALIDATION_BINDER.html
- GitHub Repository (MIT License): github.com/saram-io/gxp-historian
Saram Consulting