Metadata Ingestion
The metadata ingestion framework lives atingestion/src/metadata/ingestion/. It extracts metadata (databases, schemas, tables, columns, dashboards, pipelines, etc.) from external systems and publishes it to the OpenMetadata server.
This guide covers the core framework architecture. For usage and lineage ingestion — which build on these same patterns — see the dedicated pages.
Core Pipeline
Every ingestion workflow follows the Source → Sink pattern, orchestrated byworkflow/metadata.py:
Topology-Based Execution
The key architectural pattern is the topology. Instead of hand-coded loops, each source declares a tree ofTopologyNode objects that the framework traverses depth-first.
How It Works
A topology is a tree where each node has:producer— a method that yields raw items (e.g., database names)stages— processing steps that transform each item into an entity requestchildren— child nodes to recurse intopost_process— cleanup methods run after all children complete
Database Service Topology
This is the topology for all SQL database connectors (source/database/database_service.py):
Execution Engine
TopologyRunnerMixin (api/topology_runner.py) drives the traversal:
threads=True distribute items across a thread pool. Each thread gets a copy of the TopologyContext.
Topology Context
TopologyContext is a thread-safe state object that tracks the current position in the hierarchy. As the traversal descends, it stores the current service, database, schema, etc., so child nodes can build fully qualified names (FQNs):
Source Class Hierarchy
For database connectors, the class hierarchy is:Key Methods in CommonDbSourceService
Column Type Parsing
ColumnTypeParser (source/database/column_type_parser.py) maps database-specific types to OpenMetadata’s DataType enum:
- Handles complex types: JSON, ARRAY, STRUCT, MAP
- Extracts precision/scale for numeric types
- Supports database-specific type aliases
Constraint Handling
SqlColumnHandlerMixin (source/database/sql_column_handler.py) processes:
- Primary keys — from
inspector.get_pk_constraint() - Unique constraints — from
inspector.get_unique_constraints() - Foreign keys — from
inspector.get_foreign_keys(), including cross-database references
Other Service Topologies
The same topology pattern applies to all service types:Dashboard Service
Pipeline Service
Messaging Service
Storage, Search, ML Model, API Services
Each follows the same pattern with service-specific entity types.MetadataRestSink
The sink (sink/metadata_rest.py) uses @singledispatchmethod to route entity types:
Fingerprinting
Every entity carries asourceHash computed from its metadata. The sink uses this to decide:
- CREATE — entity doesn’t exist yet
- PATCH — entity exists but hash differs (metadata changed)
- SKIP — entity exists and hash matches (no changes)
Filtering
Filters are applied at the producer level (before any processing):databaseFilterPattern— include/exclude databases by regexschemaFilterPattern— include/exclude schemastableFilterPattern— include/exclude tables- Plus service-specific filters (topic, pipeline, dashboard, etc.)
Connection Management
source/connections.py dynamically loads and creates database connections:
- Each service type has a connection class (e.g.,
PostgresConnection,SnowflakeConnection) get_connection()resolves the class and returns a SQLAlchemy Engine or API clienttest_connection()validates connectivity before processing
Multi-Threading
Nodes can enable multi-threaded processing for parallelism:TopologyContextManager ensures each thread gets an isolated copy of the context while sharing the database connection.
OpenMetadata API Client
TheOpenMetadata class (ometa/ometa_api.py) is composed of 25+ mixins:
The underlying REST client (
ometa/client.py) handles authentication, retries, and response parsing.