Back to Blog

Auto-Provisioning: Define-and-Deploy Ontology Infrastructure

Traditional approach: How many manual steps to define a new business object?

CoomiaPublished on August 16, 202515 min read
Share this articleTwitter / X

Auto-Provisioning: Define-and-Deploy Ontology Infrastructure

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

#TL;DR

  • Auto-Provisioning makes ObjectType registration automatically trigger full-stack infrastructure creation — storage tables, indexes, API endpoints, permission configurations, SDK types, and monitoring dashboards are all created automatically. Developers only need to define the Schema.
  • The Provisioning Pipeline has 6 layers — Storage, Index, API, Permission, SDK, and Monitoring. Each layer provisions independently with rollback support; one layer's failure doesn't affect others.
  • Change-aware provisioning — not just initial creation but also incremental provisioning on Schema changes (add columns, update indexes, refresh APIs), achieving full lifecycle infrastructure automation.

#1. Why Auto-Provisioning Is Needed

#1.1 Traditional Manual Process

Code
Traditional approach: How many manual steps to define a new business object?

Step 1: Design table structure (DBA)
  → Write DDL → Review → Execute → 1-3 days

Step 2: Create ORM models (Backend dev)
  → Write Entity class → Write Repository → 1 day

Step 3: Create API endpoints (Backend dev)
  → Write Controller → Write DTO → Write docs → 2 days

Step 4: Configure permissions (Security team)
  → Create roles → Assign permissions → Configure RBAC → 1 day

Step 5: Update SDK (SDK team)
  → Generate type definitions → Publish new version → 1 day

Step 6: Configure monitoring (Ops team)
  → Create Dashboard → Configure alerts → 1 day

Total time: 7-9 days, involving 5 teams

Problems:
├── Every new ObjectType repeats this workflow
├── High coordination cost between teams
├── Manual operations are error-prone
├── Infrastructure inconsistency across ObjectTypes
└── Schema changes make updates even more complex

#1.2 coomia-dip Auto-Provisioning

Code
coomia-dip approach: Define ObjectType → everything auto-completes

Developer action:
  POST /api/v1/ontology/object-types
  {
    "objectTypeId": "ShippingOrder",
    "properties": [...],
    "relations": [...]
  }

System auto-executes (< 30 seconds):
  OK  Create storage table + partition strategy
  OK  Create indexes (primary key, foreign key, common queries)
  OK  Register CRUD API endpoints
  OK  Generate API documentation (OpenAPI)
  OK  Configure default permissions
  OK  Generate Python SDK types
  OK  Generate TypeScript SDK types
  OK  Create Grafana Dashboard
  OK  Configure basic alert rules
  OK  Register with service discovery

From 7-9 days to 30 seconds
From 5 teams to 0 teams (fully automated)

#2. Provisioning Pipeline Architecture

#2.1 Six-Layer Provisioning Pipeline

Code
Provisioning Pipeline:

┌─────────────────────────────────────────────────────┐
│  Layer 1: Storage Provisioning                       │
│  ├── Create storage tables                           │
│  ├── Configure partition strategy                    │
│  └── Set data retention policy                       │
├─────────────────────────────────────────────────────┤
│  Layer 2: Index Provisioning                         │
│  ├── Primary key index                               │
│  ├── Foreign key indexes (relation properties)       │
│  ├── Search indexes (full-text properties)           │
│  └── Custom indexes (properties marked indexed)      │
├─────────────────────────────────────────────────────┤
│  Layer 3: API Provisioning                           │
│  ├── CRUD endpoint registration                      │
│  ├── Search/filter endpoints                         │
│  ├── Batch operation endpoints                       │
│  ├── OpenAPI documentation generation                │
│  └── gRPC Service registration                       │
├─────────────────────────────────────────────────────┤
│  Layer 4: Permission Provisioning                    │
│  ├── Default role creation                           │
│  ├── CRUD permission configuration                   │
│  ├── Property-level permissions                      │
│  └── Audit log configuration                         │
├─────────────────────────────────────────────────────┤
│  Layer 5: SDK Provisioning                           │
│  ├── Python SDK type generation                      │
│  ├── TypeScript SDK type generation                  │
│  ├── SDK documentation generation                    │
│  └── Version number increment                        │
├─────────────────────────────────────────────────────┤
│  Layer 6: Monitoring Provisioning                    │
│  ├── Grafana Dashboard creation                      │
│  ├── Alert rule configuration                        │
│  ├── Log collection configuration                    │
│  └── SLO target setup                                │
└─────────────────────────────────────────────────────┘

Each layer provisions independently, supports parallel execution.
Layer 1-2 execute sequentially (indexes depend on tables).
Layer 3-6 execute in parallel (no interdependencies).

#2.2 Provisioning Event Flow

Code
Event flow during provisioning:

ObjectType registration event
  │
  ├──→ ProvisioningStarted
  │     timestamp: 2025-01-15T10:00:00.000Z
  │
  ├──→ StorageProvisioned
  │     table: "shipping_order_objects"
  │     partitionKey: "created_at"
  │     duration: 2.3s
  │
  ├──→ IndexProvisioned
  │     indexes: ["pk_shipping_order", "idx_status", "idx_created_at"]
  │     duration: 5.1s
  │
  ├──→ ApiProvisioned (parallel)
  │     endpoints: ["/api/v1/objects/ShippingOrder/*"]
  │     grpcService: "ShippingOrderService"
  │     duration: 1.2s
  │
  ├──→ PermissionProvisioned (parallel)
  │     roles: ["ShippingOrder.Reader", ".Writer", ".Admin"]
  │     duration: 0.8s
  │
  ├──→ SdkProvisioned (parallel)
  │     python: "ontology_sdk.types.ShippingOrder"
  │     typescript: "@coomia-dip/sdk/ShippingOrder"
  │     duration: 3.5s
  │
  ├──→ MonitoringProvisioned (parallel)
  │     dashboard: "ShippingOrder Overview"
  │     alerts: ["error_rate > 1%", "latency_p99 > 500ms"]
  │     duration: 2.1s
  │
  └──→ ProvisioningCompleted
        totalDuration: 12.5s
        status: SUCCESS

#3. Layer 1: Storage Provisioning

#3.1 Auto-Generated Table Structure

Code
Auto-generate DDL from ObjectType definition:

ObjectType definition:
{
  "objectTypeId": "ShippingOrder",
  "properties": [
    {"name": "orderId", "type": "STRING", "primaryKey": true},
    {"name": "status", "type": "ENUM", "values": ["PENDING","SHIPPED","DELIVERED"]},
    {"name": "totalWeight", "type": "DECIMAL", "precision": 10, "scale": 2},
    {"name": "shippingAddress", "type": "STRUCT", "fields": [
      {"name": "street", "type": "STRING"},
      {"name": "city", "type": "STRING"},
      {"name": "zipCode", "type": "STRING"}
    ]},
    {"name": "items", "type": "ARRAY", "elementType": "STRING"},
    {"name": "metadata", "type": "JSON"},
    {"name": "createdAt", "type": "TIMESTAMP", "autoGenerate": true},
    {"name": "updatedAt", "type": "TIMESTAMP", "autoUpdate": true}
  ]
}

Auto-generated DDL:

CREATE TABLE shipping_order_objects (
  -- System fields
  _onto_id        UUID DEFAULT gen_random_uuid() PRIMARY KEY,
  _onto_version   BIGINT DEFAULT 1,
  _onto_created   TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  _onto_updated   TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  _onto_deleted   BOOLEAN DEFAULT FALSE,

  -- Business properties
  order_id        VARCHAR(255) NOT NULL UNIQUE,
  status          VARCHAR(50) NOT NULL DEFAULT 'PENDING'
                  CHECK(status IN ('PENDING','SHIPPED','DELIVERED')),
  total_weight    DECIMAL(10,2),
  shipping_address JSONB,       -- STRUCT stored as JSONB
  items           TEXT[],        -- ARRAY stored as native array
  metadata        JSONB,
  created_at      TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  updated_at      TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) PARTITION BY RANGE (created_at);

-- Auto-create monthly partitions
CREATE TABLE shipping_order_objects_2025_01
  PARTITION OF shipping_order_objects
  FOR VALUES FROM ('2025-01-01') TO ('2025-02-01');

-- Trigger: auto-update updated_at
CREATE TRIGGER trg_shipping_order_updated
  BEFORE UPDATE ON shipping_order_objects
  FOR EACH ROW EXECUTE FUNCTION update_timestamp();

Type mapping rules:
  STRING → VARCHAR(255)
  TEXT → TEXT
  INT → INTEGER
  LONG → BIGINT
  DOUBLE → DOUBLE PRECISION
  DECIMAL → DECIMAL(precision, scale)
  BOOLEAN → BOOLEAN
  TIMESTAMP → TIMESTAMP WITH TIME ZONE
  DATE → DATE
  ENUM → VARCHAR(50) + CHECK constraint
  STRUCT → JSONB
  ARRAY → Native array type
  JSON → JSONB

#3.2 Partition Strategy

Code
Auto partition strategy selection:

Rules engine selects partition strategy based on ObjectType characteristics:

IF has TIMESTAMP type createdAt property:
  → Time partition (RANGE, monthly)
ELIF has ENUM type status/region property AND cardinality < 10:
  → List partition (LIST)
ELIF estimated data volume > 10 million:
  → Hash partition (HASH, 4-16 partitions)
ELSE:
  → No partitioning (small table)

Partition strategy examples:

Time partition (most common):
  PARTITION BY RANGE (created_at)
  Auto-create new partition monthly
  Expired partitions auto-archived

List partition (by status/region):
  PARTITION BY LIST (region)
  One partition per region
  Query-time automatic partition pruning

Hash partition (large table even distribution):
  PARTITION BY HASH (order_id)
  16 partitions evenly distributed
  Suitable for large tables without obvious partition keys

#4. Layer 2: Index Provisioning

#4.1 Intelligent Index Strategy

Code
Auto-created index types:

1. Primary key index (required):
   CREATE UNIQUE INDEX idx_pk_shipping_order
     ON shipping_order_objects(order_id);

2. Foreign key indexes (auto-created for relation properties):
   If ShippingOrder has customerId relation to Customer:
   CREATE INDEX idx_fk_customer
     ON shipping_order_objects(customer_id);

3. Enum indexes (auto-created for ENUM types):
   CREATE INDEX idx_status
     ON shipping_order_objects(status);

4. Time indexes (auto-created for TIMESTAMP types):
   CREATE INDEX idx_created_at
     ON shipping_order_objects(created_at);

5. Full-text search indexes (for searchable-marked properties):
   CREATE INDEX idx_search_address
     ON shipping_order_objects
     USING GIN (to_tsvector('english', shipping_address->>'street'));

6. Composite indexes (based on query pattern analysis):
   If frequent status + created_at combined queries detected:
   CREATE INDEX idx_status_created
     ON shipping_order_objects(status, created_at DESC);

Index creation strategy:
├── PK and FK indexes: Created synchronously (blocking)
├── Other indexes: Created asynchronously (CONCURRENTLY, non-blocking)
├── Full-text indexes: Deferred (after data volume threshold)
└── Composite indexes: Auto-learned from query patterns (7-day analysis)

#5. Layer 3: API Provisioning

#5.1 Auto CRUD API

Code
API endpoints auto-generated after ObjectType registration:

REST API (auto-registered in API Gateway):

GET    /api/v1/objects/ShippingOrder              # List query
GET    /api/v1/objects/ShippingOrder/{objectId}    # Single query
POST   /api/v1/objects/ShippingOrder               # Create
PUT    /api/v1/objects/ShippingOrder/{objectId}    # Full update
PATCH  /api/v1/objects/ShippingOrder/{objectId}    # Partial update
DELETE /api/v1/objects/ShippingOrder/{objectId}    # Delete (soft)
POST   /api/v1/objects/ShippingOrder/batch         # Batch ops
POST   /api/v1/objects/ShippingOrder/search        # Advanced search

gRPC Service (auto-generated .proto and registered):

service ShippingOrderService {
  rpc Get(GetShippingOrderRequest) returns (ShippingOrder);
  rpc List(ListShippingOrderRequest) returns (ListShippingOrderResponse);
  rpc Create(CreateShippingOrderRequest) returns (ShippingOrder);
  rpc Update(UpdateShippingOrderRequest) returns (ShippingOrder);
  rpc Delete(DeleteShippingOrderRequest) returns (Empty);
  rpc Search(SearchShippingOrderRequest) returns (SearchShippingOrderResponse);
  rpc BatchCreate(BatchCreateRequest) returns (BatchCreateResponse);
}

List query auto-supports:
├── Pagination: ?page=1&pageSize=20
├── Sorting: ?orderBy=createdAt&direction=DESC
├── Filtering: ?filter=status:eq:SHIPPED
├── Field selection: ?fields=orderId,status,totalWeight
└── Relation expansion: ?expand=customer,lineItems

#5.2 Auto-Generated OpenAPI Documentation

Code
Auto-generated OpenAPI 3.0 documentation:

{
  "openapi": "3.0.3",
  "info": {
    "title": "ShippingOrder API",
    "description": "Auto-generated API for ObjectType: ShippingOrder",
    "version": "v1"
  },
  "paths": {
    "/api/v1/objects/ShippingOrder": {
      "get": {
        "summary": "List ShippingOrders",
        "parameters": [
          {"name": "page", "in": "query", "schema": {"type": "integer"}},
          {"name": "pageSize", "in": "query", "schema": {"type": "integer"}},
          {"name": "filter", "in": "query", "schema": {"type": "string"}}
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {"$ref": "#/components/schemas/ShippingOrderList"}
              }
            }
          }
        }
      },
      "post": {
        "summary": "Create ShippingOrder",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {"$ref": "#/components/schemas/CreateShippingOrder"}
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "ShippingOrder": {
        "type": "object",
        "properties": {
          "orderId": {"type": "string"},
          "status": {"type": "string", "enum": ["PENDING","SHIPPED","DELIVERED"]},
          "totalWeight": {"type": "number", "format": "decimal"},
          "shippingAddress": {"$ref": "#/components/schemas/Address"},
          "createdAt": {"type": "string", "format": "date-time"}
        }
      }
    }
  }
}

Documentation auto-published to Swagger UI:
  https://platform.company.com/docs/api/ShippingOrder

#6. Layer 4: Permission Provisioning

#6.1 Default Permission Model

Code
Auto-created permission configuration:

Roles auto-created:
├── ShippingOrder.Reader   — Read-only access
├── ShippingOrder.Writer   — Read-write access
├── ShippingOrder.Admin    — Management access (incl delete + config)
└── ShippingOrder.Owner    — All permissions + permission management

Permission matrix:
┌────────────────────┬────────┬────────┬────────┬────────┐
│ Operation          │ Reader │ Writer │ Admin  │ Owner  │
├────────────────────┼────────┼────────┼────────┼────────┤
│ Read               │ Y      │ Y      │ Y      │ Y      │
│ Create             │        │ Y      │ Y      │ Y      │
│ Update             │        │ Y      │ Y      │ Y      │
│ Delete             │        │        │ Y      │ Y      │
│ Batch operations   │        │        │ Y      │ Y      │
│ Modify Schema      │        │        │        │ Y      │
│ Manage permissions │        │        │        │ Y      │
│ Export data        │        │ Y      │ Y      │ Y      │
│ View audit logs    │        │        │ Y      │ Y      │
└────────────────────┴────────┴────────┴────────┴────────┘

Property-level permissions (sensitive properties auto-detected):
  If property name contains "password", "secret", "token", "ssn", "creditCard":
  → Auto-marked as SENSITIVE
  → Not visible to Reader role
  → Writer can write but not read
  → Only Admin/Owner can read and write

#6.2 Auto Audit Log Configuration

Code
Auto-configured audit logging for each ObjectType:

Logged operations:
├── CREATE: Who created what object and when
├── UPDATE: Who modified which fields and when (with old and new values)
├── DELETE: Who deleted what object and when
├── READ: Who read what object and when (configurable)
└── EXPORT: Who exported what data and when

Audit log format:
{
  "auditId": "audit-20250115-001",
  "objectType": "ShippingOrder",
  "objectId": "SO-001",
  "action": "UPDATE",
  "actor": "alice@company.com",
  "timestamp": "2025-01-15T10:30:00Z",
  "changes": {
    "status": {"from": "PENDING", "to": "SHIPPED"},
    "updatedAt": {"from": "...", "to": "..."}
  },
  "metadata": {
    "ip": "10.0.1.100",
    "userAgent": "coomia-dip-sdk/1.0.0",
    "requestId": "req-abc-123"
  }
}

Audit log retention policy:
  CREATE/UPDATE/DELETE: Permanent retention
  READ: 90-day retention
  EXPORT: 365-day retention

#7. Layer 5: SDK Provisioning

#7.1 Python SDK Auto-Generation

Code
Auto-generated Python SDK types:

# Auto-generated: Do not edit manually
# ObjectType: ShippingOrder
# Generated at: 2025-01-15T10:00:00Z

from datetime import datetime
from decimal import Decimal
from typing import List, Optional
from pydantic import BaseModel, Field
from ontology_sdk.base import OntologyObject

class ShippingAddress(BaseModel):
    street: str
    city: str
    zip_code: str = Field(alias="zipCode")

class ShippingOrder(OntologyObject):
    """Shipping order object type"""

    object_type_id: str = "ShippingOrder"

    order_id: str = Field(..., description="Order ID", alias="orderId")
    status: str = Field(default="PENDING", description="Order status")
    total_weight: Optional[Decimal] = Field(None, alias="totalWeight")
    shipping_address: Optional[ShippingAddress] = Field(None, alias="shippingAddress")
    items: List[str] = Field(default_factory=list)
    metadata: Optional[dict] = None
    created_at: Optional[datetime] = Field(None, alias="createdAt")
    updated_at: Optional[datetime] = Field(None, alias="updatedAt")

    class Config:
        populate_by_name = True

# Auto-generated CRUD methods
class ShippingOrderClient:
    def get(self, order_id: str) -> ShippingOrder: ...
    def list(self, filter: Optional[str] = None, page: int = 1) -> List[ShippingOrder]: ...
    def create(self, order: ShippingOrder) -> ShippingOrder: ...
    def update(self, order_id: str, updates: dict) -> ShippingOrder: ...
    def delete(self, order_id: str) -> None: ...
    def search(self, query: str) -> List[ShippingOrder]: ...

#7.2 TypeScript SDK Auto-Generation

Code
Auto-generated TypeScript SDK types:

// Auto-generated: Do not edit manually
// ObjectType: ShippingOrder
// Generated at: 2025-01-15T10:00:00Z

export interface ShippingAddress {
  street: string;
  city: string;
  zipCode: string;
}

export interface ShippingOrder {
  orderId: string;
  status: 'PENDING' | 'SHIPPED' | 'DELIVERED';
  totalWeight?: number;
  shippingAddress?: ShippingAddress;
  items: string[];
  metadata?: Record<string, unknown>;
  createdAt?: string;
  updatedAt?: string;
}

export interface ShippingOrderClient {
  get(orderId: string): Promise<ShippingOrder>;
  list(options?: ListOptions): Promise<PagedResult<ShippingOrder>>;
  create(order: Omit<ShippingOrder, 'createdAt' | 'updatedAt'>): Promise<ShippingOrder>;
  update(orderId: string, updates: Partial<ShippingOrder>): Promise<ShippingOrder>;
  delete(orderId: string): Promise<void>;
  search(query: SearchQuery): Promise<PagedResult<ShippingOrder>>;
}

#8. Layer 6: Monitoring Provisioning

#8.1 Auto Dashboard Creation

Code
Auto-create Grafana Dashboard for each ObjectType:

Dashboard panels:

Row 1: Overview
├── Total object count (single stat panel)
├── Last 24h new objects (trend graph)
├── Last 24h CRUD operation distribution (pie chart)
└── Average API response time (single stat)

Row 2: Operation Metrics
├── API request volume (time series grouped by endpoint)
├── API latency P50/P95/P99 (time series)
├── Error rate (time series)
└── Active user count (time series)

Row 3: Data Metrics
├── Storage space usage (trend)
├── Distribution by status (pie chart)
├── Data growth trend (time series)
└── Data quality score (gauge)

Row 4: Alerts
├── Active alert list
└── Recent alert history

#8.2 Auto Alert Rules

Code
Auto-configured basic alert rules:

alerts:
  - name: "{ObjectType} API Error Rate High"
    condition: error_rate > 1%
    duration: 5m
    severity: WARNING

  - name: "{ObjectType} API Latency High"
    condition: latency_p99 > 500ms
    duration: 5m
    severity: WARNING

  - name: "{ObjectType} Storage Growth Abnormal"
    condition: growth_rate > 200% (vs last week)
    duration: 1h
    severity: INFO

  - name: "{ObjectType} Data Quality Drop"
    condition: quality_score < 95%
    duration: 15m
    severity: WARNING

#9. Change-Aware Provisioning

#9.1 Schema Changes Trigger Incremental Provisioning

Code
Incremental provisioning on Schema changes:

Change Type → Triggered provisioning operations:

ADD_PROPERTY:
  Storage: ALTER TABLE ADD COLUMN
  Index: If marked indexed → CREATE INDEX CONCURRENTLY
  API: Update OpenAPI documentation
  SDK: Regenerate type definitions
  Monitoring: No changes

MODIFY_PROPERTY (type change):
  Storage: ALTER TABLE ALTER COLUMN TYPE
  Index: If index affected → Rebuild index
  API: Update OpenAPI documentation
  SDK: Regenerate type definitions
  Monitoring: No changes

DELETE_PROPERTY:
  Storage: Mark column as deprecated (don't delete immediately)
  Index: Drop related indexes
  API: Update OpenAPI docs + add deprecated marker
  SDK: Mark as @deprecated
  Monitoring: Remove related panels

ADD_RELATION:
  Storage: Create foreign key index
  API: Add relation query endpoint
  SDK: Add relation navigation method
  Monitoring: Add relation metrics panel

#9.2 Provisioning Rollback

Code
Rollback strategy on provisioning failure:

Each layer records rollback information:

Layer 1 rollback (Storage):
  DROP TABLE IF EXISTS shipping_order_objects;

Layer 2 rollback (Index):
  DROP INDEX IF EXISTS idx_pk_shipping_order;
  DROP INDEX IF EXISTS idx_status;

Layer 3 rollback (API):
  Deregister endpoints from API Gateway
  Remove gRPC Service registration

Layer 4 rollback (Permission):
  Delete auto-created roles and permissions
  Revoke assigned permissions

Layer 5 rollback (SDK):
  Remove type definitions from SDK package
  Publish rollback version

Layer 6 rollback (Monitoring):
  Delete Grafana Dashboard
  Remove alert rules

Partial failure scenario:
  Layer 1-3 succeed, Layer 4 fails
  → Only rollback Layer 4-6
  → Layer 1-3 retained
  → Retry Layer 4
  → After Layer 4 succeeds, continue Layer 5-6

#10. Provisioning Templates and Customization

#10.1 Provisioning Templates

Code
Different ObjectType categories use different provisioning templates:

Template 1: Standard Business Object
  Storage: PostgreSQL + time partition
  Index: Standard index set
  API: Full CRUD
  Permission: Standard 4 roles
  SDK: Python + TypeScript
  Monitoring: Standard Dashboard

Template 2: High-Frequency Event Object
  Storage: TimescaleDB + compression
  Index: Time index + partition index
  API: Write-only + aggregate queries (no single-record query)
  Permission: Writer + Analyst
  SDK: Writer interface + aggregate interface
  Monitoring: Throughput + latency focus

Template 3: Configuration Object
  Storage: PostgreSQL (no partitioning)
  Index: Minimal index set
  API: Full CRUD + version history
  Permission: Admin read-only, Owner read-write
  SDK: Full interface
  Monitoring: Change frequency + audit focus

Template 4: Read-Only Reference Data
  Storage: PostgreSQL + heavy caching
  Index: Query-optimized indexes
  API: Read-only API
  Permission: Reader only
  SDK: Read-only interface
  Monitoring: Cache hit rate focus

#10.2 Custom Provisioning Hooks

Code
Insert custom logic during provisioning:

hooks:
  beforeStorageProvision:
    type: WEBHOOK
    url: "https://dba-approval.internal/api/review"
    timeout: 24h    # DBA approval (only for large tables)
    condition: "estimatedRowCount > 10000000"

  afterApiProvision:
    type: SCRIPT
    script: |
      # Auto-register with API gateway
      register_to_kong(objectType, endpoints)
      # Auto-configure rate limiting
      set_rate_limit(objectType, rps=1000)

  afterSdkProvision:
    type: WEBHOOK
    url: "https://ci.internal/api/trigger"
    payload:
      pipeline: "sdk-publish"
      version: "{{sdkVersion}}"

  afterMonitoringProvision:
    type: SCRIPT
    script: |
      # Auto-add to On-Call dashboard
      add_to_oncall_dashboard(objectType)
      # Auto-create PagerDuty service
      create_pagerduty_service(objectType)

#Key Takeaways

  1. Auto-provisioning compresses "7-9 days, 5 teams" into "30 seconds, zero manual effort" — after ObjectType registration, storage, indexes, APIs, permissions, SDKs, and monitoring are all created automatically. Developers focus on Schema definition while the platform handles infrastructure.
  2. The six-layer pipeline ensures reliability and recoverability — each layer provisions and rolls back independently. One layer's failure doesn't affect others. Layer 1-2 execute sequentially for dependency ordering; Layer 3-6 execute in parallel for speed.
  3. Change-aware provisioning eliminates "changed Schema, forgot to change API" — Schema changes auto-trigger incremental provisioning. New properties auto-add columns, indexes, update docs, and regenerate SDKs across the full lifecycle.
  4. Intelligent strategies minimize unnecessary provisioning — auto-select index strategy based on property type, partition strategy based on data volume, and query optimization based on usage patterns.
  5. Templates and custom hooks balance standardization with flexibility — standard business objects use the default template, high-frequency events use the event template, and special needs use hooks for custom logic insertion.

#Next Article

The next article S4-13 Connection Registry discusses how to centrally manage Ontology's external connections — database connections, API credentials, message queue configurations — how to achieve connection reuse, encrypted storage, health checks, and automatic failover.

#ontology #auto-provisioning #infrastructure-as-code #crud-generation #sdk-generation #monitoring #zero-touch #schema-driven