Design Decisions

Key design constraints, architectural rationale, tradeoffs, and extensibility notes for Molecular.

👤 Mohammad Ashfaque Alam📅 Updated: May 19, 2026📁 Molecular

Molecular Design Decisions

Use this page to capture why the feature was built this way, not only what the code does.

Design Intent

Molecular diagnostics requires strict linkage between genetic markers, the organisms that carry them, and the antimicrobial agents used to treat them. The feature is designed around a prerequisite-master-data model to ensure these relationships are structurally sound before any reporting happens.

The design premise:

Molecular reporting configuration must be built on explicit, mapped master catalogs (Genes, Organisms, Antibiotics) to enable automated resistance calculation and standardized reporting, rather than ad-hoc text entry.

Decision Stack

Key Design Constraints

ConstraintWhy it is realArchitectural consequence
Molecular targets (Genes) and targets (Organisms) share AntibioticsSusceptibility testing uses the same catalog of antimicrobial agents regardless of the diagnostic targetA single Antibiotic master table serves both Gene and Organism relationships
Organisms have standard and molecular antibiogramsSome testing uses standard culture methods, while molecular methods require specific ordering and active state trackingTwo junction tables exist: OrganismAntibiotics and MolecularOrganismAntibiotics
Detection interpretation is inverted compared to ToxicologyIn molecular testing, a value below a cut-off (e.g., lower Ct value in PCR) indicates presenceThe frontend AgGrid detection logic evaluates value <= cut_off as Detected
Master records can be operationally disabledRecords may need to stop being selectable without losing historical report integritySoft-disable flags (is_disabled) are used instead of hard deletes; linked records are protected via disable-warnings
Master records need clear synchronizationCaching layer needs to stay consistent across related entitiesAggressive cache invalidation: saving a gene updates the organism cache; saving an organism updates the gene cache

Architectural Rationale

1. Antibiotic Master is the shared foundation

Antibiotics form the core vocabulary for susceptibility testing. Both Genes and Organisms depend on them.

Why this was preferred

  • Avoids duplicating drug definitions across molecular and standard culture modules.
  • Allows a unified susceptibility reporting format.
  • Provides a single point of integration for device mapping (device_organism_mapping, device_gene_mapping).

2. Specialized Junction Tables for Organisms

The system uses OrganismAntibiotics for standard mappings, but introduces MolecularOrganismAntibiotics for molecular reports.

Why this was preferred

  • Molecular reports require specific display ordering (sequence) and the ability to toggle individual antibiotic mappings on/off (is_active) without destroying the underlying standard antibiogram.
  • The MolecularOrganismAntibiotics table is managed via upsert logic during organism save to preserve sequence and active states, unlike standard mappings which use delete-and-recreate bulk operations.

3. Inverted Detection Logic in the Frontend Grid

Instead of creating a completely separate grid architecture, Molecular reuses the report entry grid but applies a specific componentType check (GENE or ORGANISM) to alter the interpretation logic.

Why this was preferred

  • Allows maximum reuse of the AgGrid report entry components.
  • Centralizes the logic in helpers.tsx (renderCell, getColorForMolecular) based on the component type flag.

Tradeoff

  • The helpers.tsx file must carefully branch logic based on componentType, increasing the complexity of a shared file to accommodate the inverted ≤ cut_off = Detected rule.

4. Cache Invalidation Strategy

Due to the complex interdependencies (Genes map to Antibiotics, Organisms map to Antibiotics, and API responses often serialize these nested relationships), caching must be aggressively managed.

Why this was preferred

  • When a gene changes, an organism's serialized response (which might embed gene resistance data) must reflect the change. Thus, update_organism_cache() is called from Gene's after_save.
  • This bidirectional invalidation ensures that the livehealthapp read APIs always serve consistent nested mappings without requiring expensive real-time table joins on every list load.

Extensibility Notes

  • If new molecular targets (e.g., specific mutations or variants) are added, consider extending the Gene model with new fields rather than creating a new base entity, as the resistance mapping logic is already established there.
  • The dual junction table approach for Organisms (OrganismAntibiotics vs MolecularOrganismAntibiotics) should be carefully maintained. If new ordering/active-state logic is needed for standard cultures in the future, consider unifying the junction tables rather than adding a third.
  • Any new Molecular component types added to the report configuration must be explicitly handled in the renderCell and prepareSummaryComponentColumnDef helpers in the frontend grid logic.

On this page