Back to Blog

Schema Change Management: Zero-Downtime Ontology Evolution

Nightmare scenario:

CoomiaPublished on August 13, 202518 min read
Share this articleTwitter / X

Schema Change Management: Zero-Downtime Ontology Evolution

Series: S4 Ontology Modeling · Article 9 | Level: Intermediate | Reading Time: 18 min

#TL;DR

  • Ontology Schemas are not static — business evolution means ObjectTypes need new properties, type changes, and field deletions. coomia-dip provides Schema versioning and safe migration mechanisms to ensure changes never break existing data or consumers.
  • Three-phase migration protocol (Propose, Validate, Apply) ensures every Schema change goes through compatibility checking, impact analysis, and data migration verification, eliminating the "changed Schema and everything exploded" scenario.
  • Backward compatibility rules are auto-evaluated — adding optional properties (safe), modifying types (requires validation), deleting properties (dangerous) are automatically classified with migration recommendations.

#1. Why Schema Change Management Is Critical

#1.1 Schema Changes Without Version Control

Code
Nightmare scenario:

Monday: DBA changes Order.status from STRING to ENUM
Tuesday: Reporting team's ETL pipelines all fail — they use status LIKE '%active%'
Wednesday: Frontend team finds dropdowns broken — API ENUM values don't match
Thursday: Data science team's model training fails — feature column type changed
Friday: Rollback! But rollback also breaks — new ENUM values can't convert back to STRING

Root cause analysis:
├── No change impact analysis
├── No downstream consumer notification
├── No data migration plan
├── No rollback strategy
└── No compatibility checking

#1.2 coomia-dip Schema Versioning

Code
coomia-dip Schema change workflow:

┌─────────┐    ┌─────────┐    ┌─────────┐    ┌─────────┐
│ Propose │ →  │Validate │ →  │ Preview │ →  │  Apply  │
│ Submit  │    │Compat   │    │ Impact  │    │ Execute │
│ change  │    │ check   │    │ preview │    │migration│
└─────────┘    └─────────┘    └─────────┘    └─────────┘
                    │                              │
                    ↓                              ↓
              Incompatible?                  Auto data migration
              Reject or require              + version increment
              explicit confirmation

Each ObjectType has version history:
  Order v1: {orderId, status: STRING, amount: DOUBLE}
  Order v2: {orderId, status: ENUM, amount: DOUBLE, createdAt: TIMESTAMP}
  Order v3: {orderId, status: ENUM, totalAmount: DOUBLE, createdAt: TIMESTAMP}
            ↑ amount renamed to totalAmount

#2. Schema Change Classification

#2.1 Change Type Matrix

Code
Change types and risk ratings:

┌─────────────────────────┬────────┬──────────────────────────────┐
│ Change Type             │ Risk   │ Description                   │
├─────────────────────────┼────────┼──────────────────────────────┤
│ Add optional property   │ SAFE   │ Old data unaffected, optional │
│ Add required + default  │ SAFE   │ Old data auto-filled          │
│ Add index               │ SAFE   │ Async background build        │
│ Rename property         │ MEDIUM │ API consumers need update     │
│ Widen type range        │ MEDIUM │ INT→LONG, STRING→TEXT safe    │
│ Add enum value          │ MEDIUM │ Old consumers may not know it │
│ Change property type    │ HIGH   │ May cause data loss           │
│ Narrow type range       │ HIGH   │ LONG→INT may overflow         │
│ Delete property         │ HIGH   │ Dependent consumers will fail │
│ Delete enum value       │ HIGH   │ Existing data may contain it  │
│ Add required no default │ HIGH   │ Old data can't satisfy constr │
│ Change primary key      │ BLOCK  │ Breaks all relations/refs     │
└─────────────────────────┴────────┴──────────────────────────────┘

#2.2 Compatibility Rules Engine

Code
Compatibility checking engine:

Input: Current Schema + Change Request
Output: Compatibility verdict + Migration recommendations

Rule 1: Add property
  IF property nullable == true OR default != null:
    → COMPATIBLE (safe)
  ELSE:
    → BREAKING (dangerous: old data lacks this field)
    → Suggestion: Add default value or make optional

Rule 2: Type change
  Compatible type pairs (safe widening):
    BOOLEAN → STRING       ✓
    INT → LONG → DOUBLE    ✓
    STRING → TEXT           ✓
    DATE → TIMESTAMP        ✓

  Incompatible type pairs (data loss risk):
    DOUBLE → INT            ✗ (precision loss)
    STRING → INT            ✗ (format mismatch)
    TIMESTAMP → DATE        ✗ (time info lost)

Rule 3: Delete property
  Scan all dependencies:
    Derived property dependency? → BREAKING
    ActionType parameter dependency? → BREAKING
    RelationType reference? → BREAKING
    External API consumer? → WARNING
  IF no dependencies:
    → COMPATIBLE (but recommend marking @Deprecated first)

Rule 4: Enum changes
  Add value: COMPATIBLE (old consumers may need update)
  Remove value:
    IF existing data contains that value: BREAKING
    IF existing data does not contain it: COMPATIBLE (but verify)
  Rename value: BREAKING (essentially delete old + add new)

#3. Three-Phase Migration Protocol

#3.1 Phase 1: Propose

Code
API: POST /api/v1/ontology/schema/proposals

Request:
{
  "objectTypeId": "Order",
  "changes": [
    {
      "type": "ADD_PROPERTY",
      "property": {
        "name": "priority",
        "dataType": "ENUM",
        "enumValues": ["LOW", "MEDIUM", "HIGH", "URGENT"],
        "nullable": false,
        "defaultValue": "MEDIUM"
      }
    },
    {
      "type": "MODIFY_PROPERTY",
      "propertyName": "amount",
      "modifications": {
        "rename": "totalAmount",
        "dataType": "DECIMAL"
      }
    },
    {
      "type": "DEPRECATE_PROPERTY",
      "propertyName": "legacyCode",
      "deprecationMessage": "Use 'orderCode' instead",
      "removalVersion": "v5"
    }
  ],
  "description": "Add priority field, rename amount to totalAmount with DECIMAL",
  "author": "alice@company.com"
}

Response:
{
  "proposalId": "prop-20250115-001",
  "status": "PENDING_VALIDATION",
  "version": {
    "current": "v3",
    "proposed": "v4"
  },
  "changes": [...],
  "createdAt": "2025-01-15T10:00:00Z"
}

#3.2 Phase 2: Validate

Code
API: POST /api/v1/ontology/schema/proposals/{proposalId}/validate

Automatically executed checks:

┌──────────────────────────────────────────────────────┐
│  Schema Change Validation Report                      │
│  Proposal: prop-20250115-001                          │
│  ObjectType: Order (v3 → v4)                          │
├──────────────────────────────────────────────────────┤
│                                                       │
│  Change 1: ADD_PROPERTY "priority"                    │
│  ├── Compatibility: COMPATIBLE                        │
│  ├── Reason: Has default value "MEDIUM"               │
│  ├── Data migration: None required                    │
│  └── Impact: None                                     │
│                                                       │
│  Change 2: RENAME "amount" → "totalAmount"            │
│  ├── Compatibility: REQUIRES_MIGRATION                │
│  ├── Reason: Property name change                     │
│  ├── Data migration: Column rename (zero-copy)        │
│  └── Impact:                                          │
│      ├── 3 Derived Properties reference "amount"      │
│      │   → Will auto-update to "totalAmount"          │
│      ├── 2 ActionTypes use "amount" as parameter      │
│      │   → Require manual update                      │
│      ├── 1 RelationType filters on "amount"           │
│      │   → Will auto-update                           │
│      └── External APIs: /api/v1/orders response       │
│          → Add alias "amount" → "totalAmount"         │
│                                                       │
│  Change 3: TYPE_CHANGE "amount" DOUBLE → DECIMAL      │
│  ├── Compatibility: REQUIRES_MIGRATION                │
│  ├── Reason: Type widening (safe direction)           │
│  ├── Data migration: CAST(amount AS DECIMAL(18,4))    │
│  ├── Estimated time: ~30s for 1M rows                 │
│  └── Impact: None (DECIMAL is superset of DOUBLE)     │
│                                                       │
│  Change 4: DEPRECATE "legacyCode"                     │
│  ├── Compatibility: COMPATIBLE                        │
│  ├── Reason: Deprecation only, not removal            │
│  └── Impact: Consumers will see @Deprecated warning   │
│                                                       │
│  Overall: COMPATIBLE_WITH_MIGRATION                   │
│  Estimated migration time: ~35 seconds                │
│  Requires confirmation: YES (rename + type change)    │
└──────────────────────────────────────────────────────┘

#3.3 Phase 3: Apply

Code
API: POST /api/v1/ontology/schema/proposals/{proposalId}/apply

Execution process (step-by-step, each step rollbackable):

Step 1: Create new Schema version (v4)
  ├── Register v4 in Schema Registry
  ├── v3 and v4 both active (dual-version coexistence period)
  └── Duration: < 1 second

Step 2: Data migration
  ├── Add column "priority" DEFAULT 'MEDIUM'
  ├── Rename column "amount" → "totalAmount"
  ├── Type conversion DOUBLE → DECIMAL
  ├── Online DDL (no table locks)
  └── Duration: ~35 seconds

Step 3: Update derived properties
  ├── Scan all derived property expressions referencing "amount"
  ├── Auto-replace with "totalAmount"
  ├── Re-validate expression legality
  └── Duration: < 5 seconds

Step 4: Update API layer
  ├── Add property alias: amount → totalAmount
  ├── API accepts both old and new names (compatibility period)
  ├── Set compatibility period deadline (default 30 days)
  └── Duration: < 1 second

Step 5: Publish change notifications
  ├── Notify all registered Schema change listeners
  ├── Send change log to audit system
  ├── Update SDK type definitions
  └── Duration: < 1 second

Total time: ~42 seconds (35 seconds for data migration)
Zero downtime throughout, reads and writes unaffected

#4. Data Migration Strategies

#4.1 Online vs Offline Migration

Code
Online Migration — default strategy:

Applicable when:
├── Data volume < 10 million rows
├── Change type is safe widening
└── Minor performance impact acceptable (<10%)

Implementation:
  1. Double Write
     New data written in both old and new formats
  2. Background Backfill
     Background thread migrates historical data in batches
  3. Cutover
     After backfill completes, switch to new format
  4. Cleanup
     Delete old format data

Timeline:
  T0: Start double write
  T0~T1: Background backfill (minutes to hours)
  T1: Backfill complete, verify data consistency
  T2: Switch to new format
  T3: Cleanup old format data

Offline Migration — for large datasets:

Applicable when:
├── Data volume > 10 million rows
├── Change type is breaking
└── Precise verification needed

Implementation:
  1. Snapshot current data
  2. Transform on snapshot
  3. Verify transformed data
  4. Atomic switch to new data

#4.2 Type Conversion Rules

Code
Safe type conversions (auto-executed):

Source        → Target         Conversion rule
BOOLEAN       → STRING        "true" / "false"
INT           → LONG          Direct widening
INT           → DOUBLE        Direct widening
LONG          → DOUBLE        Direct widening (precision note)
FLOAT         → DOUBLE        Direct widening
STRING        → TEXT          Direct widening
DATE          → TIMESTAMP     Append "T00:00:00Z"
ENUM          → STRING        Use enum value string representation

Type conversions requiring validation (row-by-row check):

Source        → Target         Validation rule
STRING        → INT           Every row must be valid integer
STRING        → DOUBLE        Every row must be valid number
STRING        → DATE          Every row must match date format
STRING        → ENUM          Every row must be in enum values list
DOUBLE        → INT           Fractional part must be 0
TIMESTAMP     → DATE          Time portion discarded (requires confirm)

Validation report example:
┌────────────────────────────────────────────────┐
│  Type Conversion Validation                     │
│  STRING → INT for "Order.legacyAmount"          │
├────────────────────────────────────────────────┤
│  Total rows: 1,000,000                          │
│  Valid rows: 999,847                            │
│  Invalid rows: 153                              │
│                                                 │
│  Sample invalid values:                         │
│  Row 12345: "N/A"                               │
│  Row 67890: "123.45"                            │
│  Row 99001: ""                                  │
│  Row 99502: "unknown"                           │
│                                                 │
│  Action required:                               │
│  ├── Fix invalid data before migration          │
│  ├── Or provide a fallback value                │
│  └── Or change target type to allow nulls       │
└────────────────────────────────────────────────┘

#4.3 Auto-Generated Migration Scripts

Code
coomia-dip auto-generates migration scripts:

Example: Order v3 → v4 migration script

-- Migration: Order v3 → v4
-- Generated: 2025-01-15T10:05:00Z
-- Author: system (auto-generated)

-- Step 1: Add new column "priority"
ALTER TABLE order_objects
  ADD COLUMN priority VARCHAR(20) DEFAULT 'MEDIUM' NOT NULL;

-- Step 2: Rename column "amount" to "totalAmount"
ALTER TABLE order_objects
  RENAME COLUMN amount TO total_amount;

-- Step 3: Change type DOUBLE → DECIMAL
ALTER TABLE order_objects
  ALTER COLUMN total_amount TYPE DECIMAL(18,4)
  USING CAST(total_amount AS DECIMAL(18,4));

-- Step 4: Update indexes
CREATE INDEX CONCURRENTLY idx_order_priority
  ON order_objects(priority);

-- Step 5: Add deprecation marker for "legacyCode"
COMMENT ON COLUMN order_objects.legacy_code IS
  '@Deprecated: Use orderCode instead. Removal in v5.';

-- Rollback script (auto-generated):
-- ALTER TABLE order_objects DROP COLUMN priority;
-- ALTER TABLE order_objects RENAME COLUMN total_amount TO amount;
-- ALTER TABLE order_objects ALTER COLUMN amount TYPE DOUBLE PRECISION;
-- DROP INDEX idx_order_priority;

Every migration script has a corresponding rollback script.
Rollback scripts are verified for executability before Apply.

#5. Version Compatibility Management

#5.1 API Compatibility Layer

Code
After Schema changes, API must support multi-version consumers:

Scenario: Order.amount renamed to Order.totalAmount

API compatibility strategy:

v3 consumer (old) requests /api/v1/orders/123:
{
  "orderId": "123",
  "amount": 610.13,        ← old name still works
  "status": "ACTIVE"
}

v4 consumer (new) requests /api/v1/orders/123:
{
  "orderId": "123",
  "totalAmount": 610.13,   ← new name
  "priority": "HIGH",      ← new property
  "status": "ACTIVE"
}

Unversioned consumers — receive latest version

Versioned consumers:
  GET /api/v1/orders/123?schemaVersion=v3
  → Returns v3 format (using property alias mapping)

Compatibility period policy:
  v3 alias validity: 30 days after v4 release
  After 30 days: Using old name returns Deprecation Warning Header
  After 60 days: Using old name returns 400 Bad Request

#5.2 SDK Auto-Update

Code
After Schema changes, SDK auto-generates new type definitions:

Python SDK changes:

# v3 (old version)
class Order(OntologyObject):
    order_id: str
    amount: float
    status: str

# v4 (new version - auto-generated)
class Order(OntologyObject):
    order_id: str
    total_amount: Decimal        # renamed + type change
    priority: OrderPriority      # new property
    status: str
    legacy_code: str | None      # marked @deprecated

    @deprecated("Use 'total_amount' instead")
    @property
    def amount(self) -> Decimal:
        return self.total_amount

SDK versioning:
  SDK 1.0.x → Order v3
  SDK 1.1.x → Order v4 (backward compatible with v3 aliases)
  SDK 2.0.x → Order v4 (v3 aliases removed)

#5.3 Consumer Notification Mechanism

Code
Schema change notification flow:

Change proposed → Validation passes → Send notifications

Notification channels:
├── Webhook — push to registered consumer endpoints
├── Event Bus — publish to Kafka topic "schema-changes"
├── Email — send to affected ObjectType owners
└── Dashboard — display change alerts in admin console

Notification content:
{
  "eventType": "SCHEMA_CHANGE_PROPOSED",
  "objectType": "Order",
  "version": {"from": "v3", "to": "v4"},
  "changes": [
    {"type": "ADD_PROPERTY", "property": "priority"},
    {"type": "RENAME_PROPERTY", "from": "amount", "to": "totalAmount"},
    {"type": "TYPE_CHANGE", "property": "totalAmount",
     "from": "DOUBLE", "to": "DECIMAL"}
  ],
  "impact": {
    "derivedProperties": 3,
    "actionTypes": 2,
    "externalConsumers": 5
  },
  "compatibilityPeriod": "30 days",
  "proposedApplyDate": "2025-01-20T00:00:00Z"
}

Consumer responses:
├── ACK — Acknowledged, will update within compatibility period
├── NACK — Object to change, need more time
├── REQUEST_EXTENSION — Request extended compatibility period
└── No response (timeout) — System sends reminder

#6. Version Rollback

#6.1 Auto-Rollback Triggers

Code
The following conditions automatically trigger rollback:

  1. Data migration step fails
     → All executed steps are rolled back
     → Revert to pre-change Schema version

  2. Post-migration validation fails
     → Data integrity check does not pass
     → Roll back data and Schema

  3. Manual rollback trigger
     → Administrator discovers issues
     → API: POST /api/v1/ontology/schema/rollback/{version}

Rollback constraints:
├── Can only roll back to previous version (v4 → v3)
├── If new data uses new Schema-specific values, rollback must handle
│   Example: v4 added "priority" property, 1000 records already have values
│   On rollback: those 1000 records' priority values will be lost
│   → System warns and requires explicit confirmation
└── After rollback protection period (default 7 days), old version data may be cleaned

#6.2 Rollback Strategy

Code
Rollback execution steps:

Step 1: Stop new version data writes
  ├── API layer switches back to old Schema
  └── New data written using old Schema

Step 2: Data reverse-migration
  ├── Execute auto-generated rollback script
  ├── Verify reverse-migrated data integrity
  └── Handle values in new data that old Schema cannot express

Step 3: Restore dependencies
  ├── Derived property expressions restored
  ├── ActionType parameters restored
  ├── API aliases removed
  └── SDK rollback notification

Step 4: Verification
  ├── Data integrity check
  ├── Derived properties recomputation
  ├── API end-to-end testing
  └── Consumer health check

Step 5: Publish rollback notification
  ├── Notify all consumers that Schema has been rolled back
  └── Record rollback reason in audit log

#7. Schema Change Best Practices

#7.1 Incremental Changes

Code
Recommended change pattern — step by step, not all at once:

Not recommended: Direct rename and type change
  v3 → v4: amount(DOUBLE) → totalAmount(DECIMAL)
  Risk: One change contains two breaking operations

Recommended: Split into two changes
  v3 → v4: Add totalAmount(DECIMAL), keep amount
            Background sync amount → totalAmount
  v4 → v5: Mark amount as @Deprecated
  v5 → v6: After confirming no consumers use amount, delete it

Each change does one thing:
├── Either add
├── Or rename
├── Or change type
├── Or delete
└── Never mix multiple breaking operations

#7.2 Schema Change Log

Code
Every Schema change is recorded in the audit log:

SchemaChangeLog:
├── changeId: "sch-20250115-001"
├── objectTypeId: "Order"
├── versionFrom: "v3"
├── versionTo: "v4"
├── changes: [...]
├── author: "alice@company.com"
├── approver: "bob@company.com"
├── proposedAt: "2025-01-15T10:00:00Z"
├── validatedAt: "2025-01-15T10:05:00Z"
├── appliedAt: "2025-01-15T10:10:00Z"
├── migrationDurationMs: 35000
├── affectedRecords: 1000000
├── status: "COMPLETED"
└── rollbackAvailableUntil: "2025-01-22T10:10:00Z"

Query history:
  GET /api/v1/ontology/schema/changelog?objectTypeId=Order

Purposes:
├── Audit: Who changed what and when
├── Debug: What did the Schema look like at a given time
├── Compliance: Who approved the change
└── Tracing: Trace data issues back to Schema changes

#7.3 Schema Design Principles

Code
Principles for designing Schema with future changes in mind:

Principle 1: Design loosely
  ├── String fields use TEXT not VARCHAR(50)
  ├── Numeric fields use DECIMAL not INT
  ├── Date fields use TIMESTAMP not DATE
  └── Reserve extension fields (metadata: JSON)

Principle 2: Semantic naming
  ├── Use business semantics: totalAmount not amt
  ├── Use consistent naming: createdAt, updatedAt, deletedAt
  └── Avoid abbreviations: description not desc

Principle 3: Version awareness
  ├── APIs always include version numbers
  ├── Consumers declare supported version ranges
  ├── Schema changes have adequate compatibility periods
  └── Automated tests cover multi-version compatibility

Principle 4: Reversibility
  ├── Every change has a rollback plan
  ├── Deprecate before deleting
  ├── Type changes prefer safe widening direction
  └── Preserve pre-change data snapshots

#8. Automated Schema Evolution

#8.1 Schema Change Detection

Code
coomia-dip can infer Schema change needs from data patterns:

Scenario: Data mismatch detected during write

Message queue receives:
{
  "orderId": "ORD-2025-001",
  "totalAmount": 610.13,
  "priority": "HIGH",        ← Not in Schema!
  "customerSegment": "VIP"   ← Not in Schema!
}

Auto-inference flow:
  1. Detect unknown properties "priority" and "customerSegment"
  2. Analyze last 100 records, confirm this isn't sporadic dirty data
     priority appears 98/100 times, values = {LOW, MEDIUM, HIGH, URGENT}
     customerSegment appears 95/100 times, values = {VIP, REGULAR, NEW}
  3. Auto-generate Schema change proposal:
     ADD_PROPERTY priority: ENUM(LOW, MEDIUM, HIGH, URGENT)
     ADD_PROPERTY customerSegment: ENUM(VIP, REGULAR, NEW)
  4. Send notification to ObjectType owner for approval
  5. Apply automatically after approval

Note: Auto-inference can only suggest adding properties.
Type changes and deletions must be initiated manually.

#8.2 Schema Diff Comparison

Code
API: GET /api/v1/ontology/schema/diff?from=v3&to=v4&objectTypeId=Order

Response:
{
  "objectTypeId": "Order",
  "from": "v3",
  "to": "v4",
  "diff": {
    "added": [
      {"name": "priority", "type": "ENUM",
       "values": ["LOW","MEDIUM","HIGH","URGENT"]}
    ],
    "modified": [
      {
        "name": "amount → totalAmount",
        "changes": {
          "name": {"from": "amount", "to": "totalAmount"},
          "type": {"from": "DOUBLE", "to": "DECIMAL(18,4)"}
        }
      }
    ],
    "deprecated": [
      {"name": "legacyCode", "message": "Use orderCode instead",
       "removalVersion": "v5"}
    ],
    "removed": []
  },
  "compatibility": "BACKWARD_COMPATIBLE_WITH_MIGRATION",
  "migrationRequired": true
}

#9. Multi-Environment Schema Synchronization

#9.1 Environment Promotion Flow

Code
Schema changes promoted across environments:

Development (dev) → Staging (staging) → Production (prod)

Flow:
  1. dev environment: Free changes, no approval needed
  2. staging environment: Sync Schema from dev, run integration tests
  3. prod environment: Promote from staging, requires approval

Schema sync API:
  POST /api/v1/ontology/schema/promote
  {
    "objectTypeId": "Order",
    "fromEnvironment": "staging",
    "toEnvironment": "prod",
    "version": "v4"
  }

Pre-promotion checks:
├── All integration tests pass in staging
├── Data migration verified in staging
├── Consumer compatibility tests pass
├── Rollback plan is ready
└── Approver has approved

#9.2 Schema Locking

Code
Schema locking mechanism for critical ObjectTypes:

Lock levels:
  UNLOCKED    — Anyone can change
  SOFT_LOCK   — Changes require owner approval
  HARD_LOCK   — Changes require multi-person approval (2/3 approvers)
  FROZEN      — No changes allowed (unless unfrozen)

Set lock:
  PUT /api/v1/ontology/schema/lock
  {
    "objectTypeId": "Order",
    "lockLevel": "HARD_LOCK",
    "approvers": ["alice", "bob", "carol"],
    "reason": "Production release freeze"
  }

Use cases:
├── Release freeze: FROZEN
├── Core model protection: HARD_LOCK
├── Day-to-day governance: SOFT_LOCK
└── Experimental models: UNLOCKED

#10. Schema Changes and Derived Property DAG Interaction

Code
Schema changes affect the DAG:

Scenario: Rename Order.amount → Order.totalAmount

DAG impact analysis:
  1. Scan all DAG nodes referencing "Order.amount"
  2. Found:
     Customer.lifetimeValue expression references Order.amount
     Order.profit expression references amount
  3. Auto-update:
     Customer.lifetimeValue: "SUM(Order.amount)" → "SUM(Order.totalAmount)"
     Order.profit: "amount - cost" → "totalAmount - cost"
  4. Re-validate DAG:
     Expression syntax check ✓
     Cycle detection ✓
     Type compatibility check ✓

Scenario: Delete Order.legacyField

DAG impact analysis:
  1. Scan all DAG nodes referencing "Order.legacyField"
  2. Found: Order.legacyScore = legacyField * 0.5
  3. Conclusion: Cannot delete! legacyField is a derived property dependency
  4. Suggestion: Delete Order.legacyScore first, then delete Order.legacyField

Operation order:
  Step 1: Delete derived property Order.legacyScore
  Step 2: Remove legacyScore node from DAG
  Step 3: Delete source property Order.legacyField
  Step 4: Re-validate DAG integrity

#Key Takeaways

  1. Schema change is the norm for Ontology evolution — coomia-dip transforms Schema changes from "high-risk operations" to "controlled daily procedures" through versioning, compatibility checking, and auto-migration, eliminating the fear of "changing Schema breaks everything."
  2. The three-phase protocol is the safety valve — Propose (record intent) then Validate (auto-check) then Apply (controlled execution). Each phase can be interrupted and rolled back, ensuring no "system unavailable mid-change" scenarios.
  3. The compatibility rules engine auto-classifies — safe changes pass automatically, dangerous changes require confirmation, forbidden changes are rejected outright, not relying on human judgment for safety.
  4. Multi-version API and SDK support — through property aliases and version negotiation, old and new consumers coexist peacefully, giving downstream adequate migration time.
  5. Schema changes interlock with the DAG — renaming properties auto-updates derived property expressions, deleting properties first checks DAG dependencies, ensuring Schema changes never silently break computation chains.

#Next Article

The next article S4-10 Metrics as Ontology discusses how to unify monitoring metrics and business KPIs into the Ontology model — no longer treating metrics as a separate system but making them part of ObjectTypes, enabling unified querying and correlated analysis of "business data" and "operational metrics."

#ontology #schema-evolution #version-control #migration #backward-compatibility #breaking-change #data-migration #api-versioning