Implement enterprise data governance. Covers data classification, data catalog tools, access policies, data stewardship, metadata management, and compliance for data assets.
Data governance defines how data is managed, used, and controlled within an organisation. It establishes policies, roles, and standards for data quality, security, and compliance. Data catalog is the mechanism through which these governed assets are documented, discovered, and accessed. This page covers practical aspects of setting up and maintaining a data governance system with a catalog, focusing on what you need to do rather than abstract principles.
Metadata about data assets must be stored in a structured way. A minimal implementation uses a relational database table:
CREATE TABLE data_asset (
id UUID PRIMARY KEY,
name VARCHAR(255) NOT NULL,
description TEXT,
owner VARCHAR(255),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
schema JSONB,
tags TEXT[],
lineage JSONB
);
Use psql to insert initial data:
psql -d your_database -c "
INSERT INTO data_asset (id, name, description, owner, schema)
VALUES (
'123e4567-e89b-12d3-a456-426614174000',
'customer_orders',
'Orders from customers with timestamps',
'data-team',
'{\"fields\": [{\"name\": \"order_id\", \"type\": \"string\"}, {\"name\": \"customer_id\", \"type\": \"string\"}]}'
);
"
Each data asset must be registered in the catalog. The registration process involves:
Use a simple HTTP endpoint to register assets:
curl -X POST http://catalog.example.com/api/v1/assets \
-H "Content-Type: application/json" \
-d '{
"id": "123e4567-e89b-12d3-a456-426614174000",
"name": "customer_orders",
"description": "Orders from customers with timestamps",
"owner": "data-team",
"schema": {
"fields": [
{"name": "order_id", "type": "string"},
{"name": "customer_id", "type": "string"}
]
}
}'
The response should include a status code and metadata:
{
"status": "success",
"asset_id": "123e4567-e89b-12d3-a456-426614174000",
"version": "1.0"
}
Ownership defines who is responsible for a data asset. It's critical for access control and accountability. The ownership model includes:
Use a database table to track ownership:
CREATE TABLE asset_ownership (
asset_id UUID REFERENCES data_asset(id),
role VARCHAR(50),
user_or_group VARCHAR(255),
PRIMARY KEY (asset_id, role, user_or_group)
);
To update ownership:
curl -X PUT http://catalog.example.com/api/v1/assets/123e4567-e89b-12d3-a456-426614174000/ownership \
-H "Content-Type: application/json" \
-d '{
"primary_owner": "data-team",
"secondary_owners": ["analyst-team"],
"access_groups": ["business-users"]
}'
Data quality rules specify what constitutes valid data for a particular asset. These rules are enforced during ingestion and reported in the catalog.
Example rule definition:
curl -X POST http://catalog.example.com/api/v1/assets/123e4567-e89b-12d3-a456-426614174000/rules \
-H "Content-Type: application/json" \
-d '{
"rule_name": "customer_id_not_null",
"description": "Customer ID must not be null",
"type": "null_check",
"field": "customer_id"
}'
Tags provide a flexible way to categorize assets. They are stored as an array in the metadata table.
curl -X PUT http://catalog.example.com/api/v1/assets/123e4567-e89b-12d3-a456-426614174000 \
-H "Content-Type: application/json" \
-d '{
"tags": ["finance", "customer", "daily"]
}'
Tags are case-sensitive and should follow a consistent naming convention. Common patterns include:
department (e.g., marketing, sales)data_type (e.g., transactional, analytical)sensitivity (e.g., public, confidential, restricted)Schema definitions are stored in JSON format and should include field names, types, and constraints. The schema is versioned.
curl -X PUT http://catalog.example.com/api/v1/assets/123e4567-e89b-12d3-a456-426614174000/schema \
-H "Content-Type: application/json" \
-d '{
"version": "1.0",
"fields": [
{"name": "order_id", "type": "string", "nullable": false},
{"name": "customer_id", "type": "string", "nullable": false},
{"name": "order_date", "type": "timestamp", "nullable": true}
]
}'
Access control is managed through roles and permissions. A minimal implementation uses a table for mapping users to asset access:
CREATE TABLE asset_access (
asset_id UUID REFERENCES data_asset(id),
user_or_group VARCHAR(255),
permission VARCHAR(20),
PRIMARY KEY (asset_id, user_or_group, permission)
);
Permissions are read, write, and admin. Example access update:
curl -X PUT http://catalog.example.com/api/v1/assets/123e4567-e89b-12d3-a456-426614174000/access \
-H "Content-Type: application/json" \
-d '{
"access": [
{"user_or_group": "data-team", "permission": "read"},
{"user_or_group": "analyst-team", "permission": "read"},
{"user_or_group": "admin-team", "permission": "admin"}
]
}'
Each change to an asset should create a new version. This is managed through a versioning system that tracks schema changes, metadata updates, and ownership modifications.
curl -X POST http://catalog.example.com/api/v1/assets/123e4567-e89b-12d3-a456-426614174000/versions \
-H "Content-Type: application/json" \
-d '{
"description": "Added order_date field",
"changes": [
{"field": "order_date", "type": "timestamp"}
]
}'
Lineage shows how data flows from source to destination. It's stored as a JSON object with source and target information.
curl -X PUT http://catalog.example.com/api/v1/assets/123e4567-e89b-12d3-a456-426614174000/lineage \
-H "Content-Type: application/json" \
-d '{
"source": "orders_raw",
"destination": "orders_enriched",
"transformation": "join_customer_data"
}'
Search and filter functionality allows users to find assets by name, tags, owner, or schema.
Example search query:
curl -X GET 'http://catalog.example.com/api/v1/assets?tag=customer&owner=data-team'
Response includes a list of matching assets with basic metadata:
{
"assets": [
{
"id": "123e4567-e89b-12d3-a456-426614174000",
"name": "customer_orders",
"description": "Orders from customers with timestamps",
"owner": "data-team",
"tags": ["customer", "finance"]
}
]
}
Catalog operations return specific HTTP status codes:
200 OK for successful operations400 Bad Request for malformed input or validation errors401 Unauthorized for access denied404 Not Found for missing assets409 Conflict when trying to create a duplicate assetExample error response:
{
"error": "Asset already exists",
"code": "ASSET_EXISTS",
"status": 409
}
Customer is different from customer.customer, Customer, and CUSTOMER can exist simultaneously, making search unreliable.Set up monitoring for:
Example health check endpoint:
curl -X GET http://catalog.example.com/health
Response should be:
{
"status": "healthy",
"timestamp": "2023-10-01T10:00:00Z"
}
When migrating from an older catalog system:
Example migration command:
curl -X POST http://catalog.example.com/api/v1/migrate \
-H "Content-Type: application/json" \
-d '{
"source_system": "old-catalog",
"assets_file": "/path/to/assets.json"
}'
The process should return a summary of imported assets and any errors encountered.
This page was rewritten on 16 October 2026. It replaced a templated version that was not specific to its own title. How these pages are written and checked. If anything here is wrong, tell us at [email protected] and we will correct it.
We use cookies for analytics (Google Analytics) and advertising (Google AdSense) to improve your experience and support free content. Privacy Policy