Pipeline Examples¶
This guide provides comprehensive, real-world pipeline examples in all supported formats: YAML, JSON, and HOCON.
Format Comparison¶
The same pipeline expressed in all three supported configuration formats:
name: customer-daily-load
tenancy: acme-corp
namespace: production
dataset: customers
executionMode: batch
platformProfile: databricks
schedule: "0 6 * * *"
stages:
- name: acquire-customers
type: source
capability: source-acquisition
provider: spark-file-source
timeout: PT5M
config:
path: /data/input/customers.csv
format: csv
- name: transform-customers
type: transformation
capability: transformation
timeout: PT10M
transformation:
sql:
style: sql
reference: "SELECT id, name, UPPER(city) AS city FROM {input} WHERE active = true"
- name: write-output
type: publish
capability: storage
provider: spark-file-storage
timeout: PT5M
config:
format: parquet
mode: overwrite
policies: []
extensions: []
{
"name": "customer-daily-load",
"tenancy": "acme-corp",
"namespace": "production",
"dataset": "customers",
"executionMode": "batch",
"platformProfile": "databricks",
"schedule": "0 6 * * *",
"stages": [
{
"name": "acquire-customers",
"type": "source",
"capability": "source-acquisition",
"provider": "spark-file-source",
"timeout": "PT5M",
"config": {
"path": "/data/input/customers.csv",
"format": "csv"
}
},
{
"name": "transform-customers",
"type": "transformation",
"capability": "transformation",
"timeout": "PT10M",
"transformation": {
"sql": {
"style": "sql",
"reference": "SELECT id, name, UPPER(city) AS city FROM {input} WHERE active = true"
}
}
},
{
"name": "write-output",
"type": "publish",
"capability": "storage",
"provider": "spark-file-storage",
"timeout": "PT5M",
"config": {
"format": "parquet",
"mode": "overwrite"
}
}
],
"policies": [],
"extensions": []
}
name = "customer-daily-load"
tenancy = "acme-corp"
namespace = "production"
dataset = "customers"
executionMode = "batch"
platformProfile = "databricks"
schedule = "0 6 * * *"
stages = [
{
name = "acquire-customers"
type = "source"
capability = "source-acquisition"
provider = "spark-file-source"
timeout = "PT5M"
config {
path = "/data/input/customers.csv"
format = "csv"
}
},
{
name = "transform-customers"
type = "transformation"
capability = "transformation"
timeout = "PT10M"
transformation {
sql {
style = "sql"
reference = "SELECT id, name, UPPER(city) AS city FROM {input} WHERE active = true"
}
}
},
{
name = "write-output"
type = "publish"
capability = "storage"
provider = "spark-file-storage"
timeout = "PT5M"
config {
format = "parquet"
mode = "overwrite"
}
}
]
policies = []
extensions = []
Choosing a format
YAML is the recommended default — concise and human-readable. JSON works well for programmatic generation. HOCON is ideal for teams familiar with Typesafe/Lightbend ecosystems and offers features like variable substitution and includes.
File ETL Examples¶
1. CSV to Parquet¶
Basic ETL: read CSV files, filter rows, select columns, write as Parquet.
name: csv-to-parquet
tenancy: data-team
namespace: production
dataset: sales-records
executionMode: batch
schedule: "0 2 * * *"
stages:
- name: read-csv-files
type: source
capability: source-acquisition
provider: spark-file-source
timeout: PT10M
config:
path: /data/raw/sales/
format: csv
header: true
inferSchema: true
delimiter: ","
- name: filter-and-project
type: transformation
capability: transformation
provider: spark-transformation
timeout: PT5M
transformation:
sql:
style: sql
reference: |
SELECT
order_id, customer_id, product_name,
quantity, unit_price,
quantity * unit_price AS total_amount,
order_date
FROM {input}
WHERE quantity > 0 AND unit_price > 0
- name: write-parquet
type: publish
capability: storage
provider: spark-file-storage
timeout: PT5M
config:
format: parquet
mode: overwrite
partitionBy: order_date
policies: []
extensions: []
Key points:
inferSchema: truelets Spark detect column types from CSV data- The transformation filters invalid rows and computes a derived column
- Output is partitioned by
order_datefor efficient downstream queries
2. JSON Events to Delta Lake¶
Process JSON event files with data quality validation before writing to Delta Lake.
name: events-to-delta
tenancy: analytics-team
namespace: production
dataset: user-events
executionMode: batch
platformProfile: databricks
schedule: "*/15 * * * *"
stages:
- name: ingest-json-events
type: source
capability: source-acquisition
provider: spark-file-source
timeout: PT10M
config:
path: /data/landing/events/
format: json
multiLine: true
- name: validate-events
type: quality
capability: data-quality
timeout: PT3M
- name: enrich-events
type: transformation
capability: transformation
provider: spark-transformation
timeout: PT10M
transformation:
sql:
style: sql
reference: |
SELECT
event_id, user_id, event_type,
event_timestamp,
CAST(event_timestamp AS DATE) AS event_date,
properties,
current_timestamp() AS processed_at
FROM {input}
WHERE event_id IS NOT NULL
- name: write-delta-lake
type: publish
capability: storage
provider: spark-file-storage
timeout: PT5M
config:
format: delta
mode: append
partitionBy: event_date
policies: []
extensions: []
Key points:
multiLine: truehandles JSON files with pretty-printed objects- Quality validation stage catches malformed events before processing
- Delta Lake append mode supports incremental writes with ACID guarantees
3. Multi-Source Merge¶
Read from multiple directories, union the data, and aggregate.
name: multi-source-merge
tenancy: data-platform
namespace: production
dataset: unified-transactions
executionMode: batch
schedule: "0 4 * * *"
stages:
- name: acquire-online-sales
type: source
capability: source-acquisition
provider: spark-file-source
timeout: PT10M
config:
path: /data/raw/online-sales/
format: parquet
- name: acquire-store-sales
type: source
capability: source-acquisition
provider: spark-file-source
timeout: PT10M
config:
path: /data/raw/store-sales/
format: parquet
- name: union-and-aggregate
type: transformation
capability: transformation
provider: spark-transformation
timeout: PT15M
transformation:
sql:
style: sql
reference: |
SELECT
region,
product_category,
SUM(amount) AS total_revenue,
COUNT(*) AS transaction_count,
AVG(amount) AS avg_transaction_value
FROM {input}
GROUP BY region, product_category
- name: write-summary
type: publish
capability: storage
provider: spark-file-storage
timeout: PT5M
config:
format: parquet
mode: overwrite
partitionBy: region
policies: []
extensions: []
Key points:
- Multiple source stages feed into a single transformation
- The aggregation groups by region and product category
- Output is partitioned by region for efficient regional queries
4. Incremental File Load¶
File-based incremental processing with checkpoint tracking.
name: incremental-file-load
tenancy: data-team
namespace: production
dataset: order-updates
executionMode: batch
schedule: "0 * * * *"
stages:
- name: acquire-new-files
type: source
capability: source-acquisition
provider: spark-file-source
timeout: PT10M
config:
path: /data/landing/orders/
format: parquet
mode: incremental
- name: deduplicate
type: transformation
capability: transformation
provider: spark-transformation
timeout: PT5M
transformation:
sql:
style: sql
reference: |
SELECT * FROM (
SELECT *,
ROW_NUMBER() OVER (PARTITION BY order_id ORDER BY updated_at DESC) AS rn
FROM {input}
) WHERE rn = 1
- name: append-to-lake
type: publish
capability: storage
provider: spark-file-storage
timeout: PT5M
config:
format: delta
mode: append
policies: []
extensions: []
Key points:
mode: incrementalreads only files modified since the last checkpoint- Deduplication ensures only the latest version of each order is kept
- Hourly schedule with append mode builds up the Delta Lake incrementally
Database ETL Examples¶
5. Full Table Extract¶
Snapshot a database table to Parquet for analytics.
name: full-table-extract
tenancy: analytics
namespace: production
dataset: product-catalog
executionMode: batch
schedule: "0 1 * * *"
stages:
- name: extract-products
type: source
capability: source-acquisition
provider: spark-jdbc-source
timeout: PT15M
config:
url: jdbc:postgresql://prod-db:5432/catalog
table: products
driver: org.postgresql.Driver
user: reader
password: ${DB_PASSWORD}
fetchSize: 5000
- name: write-snapshot
type: publish
capability: storage
provider: spark-file-storage
timeout: PT5M
config:
format: parquet
mode: overwrite
policies: []
extensions: []
Key points:
- Full table snapshot runs nightly for analytics consumption
fetchSize: 5000optimises JDBC read performance- Credentials use environment variable substitution (
${DB_PASSWORD})
6. Incremental Database Sync¶
Watermark-based incremental load from a source database.
name: incremental-db-sync
tenancy: data-platform
namespace: production
dataset: customer-orders
executionMode: batch
schedule: "*/30 * * * *"
stages:
- name: acquire-new-orders
type: source
capability: source-acquisition
provider: spark-jdbc-source
timeout: PT10M
config:
url: jdbc:postgresql://orders-db:5432/orders
table: customer_orders
driver: org.postgresql.Driver
user: etl_reader
password: ${ORDERS_DB_PASSWORD}
watermarkColumn: updated_at
watermarkValue: "2024-01-15T00:00:00"
- name: standardise-timestamps
type: transformation
capability: transformation
provider: spark-transformation
timeout: PT5M
transformation:
sql:
style: sql
reference: |
SELECT *,
CAST(updated_at AS TIMESTAMP) AS sync_timestamp,
current_timestamp() AS ingested_at
FROM {input}
- name: append-to-lake
type: publish
capability: storage
provider: spark-file-storage
timeout: PT5M
config:
format: delta
mode: append
policies: []
extensions: []
Key points:
watermarkColumnandwatermarkValueenable incremental reads (only rows whereupdated_at > watermarkValue)- The watermark value is typically managed by the Echo service and updated after each successful run
- Runs every 30 minutes to keep the data lake near real-time
7. Database to Database¶
Extract from source database, transform, and load into a target database.
name: db-to-db-sync
tenancy: data-platform
namespace: production
dataset: customer-summary
executionMode: batch
schedule: "0 3 * * *"
stages:
- name: extract-orders
type: source
capability: source-acquisition
provider: spark-jdbc-source
timeout: PT15M
config:
url: jdbc:postgresql://source-db:5432/transactions
table: orders
driver: org.postgresql.Driver
user: reader
password: ${SOURCE_DB_PASSWORD}
fetchSize: 10000
- name: aggregate-by-customer
type: transformation
capability: transformation
provider: spark-transformation
timeout: PT10M
transformation:
sql:
style: sql
reference: |
SELECT
customer_id,
COUNT(*) AS total_orders,
SUM(amount) AS lifetime_value,
MAX(order_date) AS last_order_date,
MIN(order_date) AS first_order_date
FROM {input}
GROUP BY customer_id
- name: load-to-analytics-db
type: publish
capability: storage
provider: spark-jdbc-storage
timeout: PT10M
config:
url: jdbc:postgresql://analytics-db:5432/warehouse
table: customer_summary
driver: org.postgresql.Driver
mode: overwrite
batchSize: 5000
policies: []
extensions: []
Key points:
- Source and target are different databases — common in data warehouse patterns
- Aggregation reduces millions of order rows to one row per customer
batchSize: 5000optimises bulk insert performance
8. Partitioned Large Table Read¶
Parallel JDBC reads for large tables using partition columns.
name: large-table-parallel-read
tenancy: data-platform
namespace: production
dataset: transaction-history
executionMode: batch
schedule: "0 0 * * 0"
stages:
- name: parallel-extract
type: source
capability: source-acquisition
provider: spark-jdbc-source
timeout: PT60M
config:
url: jdbc:postgresql://warehouse:5432/history
table: transactions
driver: org.postgresql.Driver
user: bulk_reader
password: ${WAREHOUSE_PASSWORD}
partitionColumn: id
lowerBound: 1
upperBound: 50000000
numPartitions: 32
fetchSize: 10000
- name: write-partitioned
type: publish
capability: storage
provider: spark-file-storage
timeout: PT15M
config:
format: parquet
mode: overwrite
partitionBy: transaction_year,transaction_month
policies: []
extensions: []
Key points:
numPartitions: 32creates 32 parallel JDBC connections for fast extractionpartitionColumn,lowerBound,upperBounddefine how Spark splits the reads- Weekly schedule for full historical snapshots
- Output partitioned by year/month for time-based query patterns
Transformation Patterns¶
9. Multi-Stage Pipeline¶
Source → Clean → Enrich → Aggregate → Publish — a classic data engineering pattern.
name: multi-stage-etl
tenancy: data-platform
namespace: production
dataset: revenue-report
executionMode: batch
platformProfile: databricks
schedule: "0 5 * * *"
stages:
- name: acquire-transactions
type: source
capability: source-acquisition
provider: spark-file-source
timeout: PT10M
config:
path: /data/lake/transactions/
format: delta
- name: clean-data
type: transformation
capability: transformation
provider: spark-transformation
timeout: PT5M
transformation:
sql:
style: sql
reference: |
SELECT * FROM {input}
WHERE amount IS NOT NULL
AND amount > 0
AND customer_id IS NOT NULL
AND transaction_date >= '2024-01-01'
- name: enrich-with-customer
type: transformation
capability: transformation
provider: spark-transformation
timeout: PT10M
transformation:
sql:
style: sql
reference: |
SELECT
t.*,
c.segment AS customer_segment,
c.region AS customer_region
FROM {input} t
JOIN customer_dim c ON t.customer_id = c.id
- name: aggregate-revenue
type: transformation
capability: transformation
provider: spark-transformation
timeout: PT10M
transformation:
sql:
style: sql
reference: |
SELECT
customer_region,
customer_segment,
CAST(transaction_date AS DATE) AS report_date,
SUM(amount) AS total_revenue,
COUNT(DISTINCT customer_id) AS unique_customers,
COUNT(*) AS transaction_count
FROM {input}
GROUP BY customer_region, customer_segment, CAST(transaction_date AS DATE)
- name: publish-report
type: publish
capability: storage
provider: spark-file-storage
timeout: PT5M
config:
format: delta
mode: overwrite
partitionBy: report_date
policies: []
extensions: []
Key points:
- Each stage has a single responsibility: clean, enrich, aggregate
- Intermediate results flow automatically between stages
- The enrichment join adds dimensional attributes for reporting
- Final output is a date-partitioned Delta table for dashboards
10. Data Quality Pipeline¶
Source → Validate → Route (quarantine bad records / pass good records) → Write.
name: quality-gated-pipeline
tenancy: data-governance
namespace: production
dataset: validated-customers
executionMode: batch
schedule: "0 3 * * *"
stages:
- name: acquire-raw-customers
type: source
capability: source-acquisition
provider: spark-file-source
timeout: PT5M
config:
path: /data/landing/customers/
format: csv
header: true
inferSchema: true
- name: validate-data-quality
type: quality
capability: data-quality
timeout: PT5M
- name: filter-valid-records
type: transformation
capability: transformation
provider: spark-transformation
timeout: PT5M
transformation:
sql:
style: sql
reference: |
SELECT * FROM {input}
WHERE email IS NOT NULL
AND email LIKE '%@%.%'
AND LENGTH(name) > 0
AND age BETWEEN 0 AND 150
- name: write-validated
type: publish
capability: storage
provider: spark-file-storage
timeout: PT5M
config:
format: parquet
mode: overwrite
policies: []
extensions: []
Key points:
- Quality stage runs framework-level validation rules
- Transformation stage applies business-specific validation logic
- Invalid records are filtered out (could also be routed to a quarantine table)
- Only clean data reaches the final output
11. Deduplication Pipeline¶
Remove duplicate records based on a business key, keeping the most recent version.
name: deduplication-pipeline
tenancy: data-platform
namespace: production
dataset: unique-events
executionMode: batch
schedule: "0 2 * * *"
stages:
- name: acquire-events
type: source
capability: source-acquisition
provider: spark-file-source
timeout: PT10M
config:
path: /data/raw/events/
format: parquet
mergeSchema: true
- name: deduplicate-by-key
type: transformation
capability: transformation
provider: spark-transformation
timeout: PT10M
transformation:
sql:
style: sql
reference: |
SELECT * FROM (
SELECT *,
ROW_NUMBER() OVER (
PARTITION BY event_id
ORDER BY event_timestamp DESC
) AS row_num
FROM {input}
) ranked
WHERE row_num = 1
- name: write-deduplicated
type: publish
capability: storage
provider: spark-file-storage
timeout: PT5M
config:
format: delta
mode: overwrite
policies: []
extensions: []
Key points:
ROW_NUMBER()window function keeps only the latest record perevent_idmergeSchema: truehandles schema evolution across Parquet files- Common pattern for event sourcing systems where duplicates are expected
12. Pivot/Unpivot for Reporting¶
Reshape data from long format to wide format for reporting dashboards.
name: pivot-for-reporting
tenancy: analytics
namespace: production
dataset: monthly-metrics-wide
executionMode: batch
schedule: "0 6 1 * *"
stages:
- name: acquire-metrics
type: source
capability: source-acquisition
provider: spark-file-source
timeout: PT5M
config:
path: /data/lake/monthly-metrics/
format: parquet
- name: pivot-metrics
type: transformation
capability: transformation
provider: spark-transformation
timeout: PT10M
transformation:
sql:
style: sql
reference: |
SELECT
department,
SUM(CASE WHEN metric_name = 'revenue' THEN metric_value ELSE 0 END) AS revenue,
SUM(CASE WHEN metric_name = 'cost' THEN metric_value ELSE 0 END) AS cost,
SUM(CASE WHEN metric_name = 'headcount' THEN metric_value ELSE 0 END) AS headcount,
SUM(CASE WHEN metric_name = 'revenue' THEN metric_value ELSE 0 END) -
SUM(CASE WHEN metric_name = 'cost' THEN metric_value ELSE 0 END) AS profit
FROM {input}
WHERE report_month = '2024-01'
GROUP BY department
- name: write-wide-report
type: publish
capability: storage
provider: spark-file-storage
timeout: PT5M
config:
format: parquet
mode: overwrite
policies: []
extensions: []
Key points:
- Conditional aggregation (
CASE WHEN) pivots rows into columns - Derived column (
profit) computed inline - Monthly schedule runs on the 1st of each month
- Wide format is optimised for BI tool consumption
Streaming Examples (Flink)¶
13. File Monitoring¶
Watch a directory for new files and process them continuously.
name: file-monitor-stream
tenancy: data-platform
namespace: production
dataset: realtime-orders
executionMode: streaming
platformProfile: aws-native
stages:
- name: monitor-landing-zone
type: source
capability: source-acquisition
provider: flink-file-source
timeout: PT0S
config:
path: /data/landing/orders/
format: json
monitorInterval: PT30S
- name: parse-and-validate
type: transformation
capability: transformation
provider: flink-transformation
timeout: PT0S
transformation:
sql:
style: sql
reference: |
SELECT
order_id, customer_id, amount, order_timestamp,
CASE WHEN amount > 0 THEN 'valid' ELSE 'invalid' END AS status
FROM {input}
WHERE order_id IS NOT NULL
- name: write-to-lake
type: publish
capability: storage
provider: flink-file-sink
timeout: PT0S
config:
format: parquet
mode: append
checkpointInterval: PT1M
policies: []
extensions: []
Key points:
executionMode: streamingenables continuous processingmonitorInterval: PT30Schecks for new files every 30 secondstimeout: PT0Smeans stages run indefinitely (streaming semantics)- Checkpoint interval ensures exactly-once delivery guarantees
14. Windowed Aggregation¶
5-minute tumbling window aggregation for real-time metrics.
name: windowed-metrics
tenancy: analytics
namespace: production
dataset: realtime-metrics
executionMode: streaming
platformProfile: aws-native
stages:
- name: consume-events
type: source
capability: source-acquisition
provider: flink-kafka-source
timeout: PT0S
config:
bootstrapServers: kafka-cluster:9092
topic: user-events
groupId: metrics-aggregator
startingOffsets: latest
- name: window-aggregate
type: transformation
capability: transformation
provider: flink-transformation
timeout: PT0S
transformation:
sql:
style: sql
reference: |
SELECT
event_type,
TUMBLE_START(event_time, INTERVAL '5' MINUTE) AS window_start,
TUMBLE_END(event_time, INTERVAL '5' MINUTE) AS window_end,
COUNT(*) AS event_count,
COUNT(DISTINCT user_id) AS unique_users
FROM {input}
GROUP BY event_type, TUMBLE(event_time, INTERVAL '5' MINUTE)
- name: emit-metrics
type: publish
capability: storage
provider: flink-kafka-sink
timeout: PT0S
config:
bootstrapServers: kafka-cluster:9092
topic: aggregated-metrics
policies: []
extensions: []
Key points:
- Kafka source with
startingOffsets: latestfor real-time processing TUMBLEwindow function creates non-overlapping 5-minute windows- Output goes back to Kafka for downstream consumers (dashboards, alerts)
- Flink handles watermarks and late data automatically
Advanced Patterns¶
15. Dual-Mode Transformation¶
Use both Spark DataFrame API and SQL for platform portability.
name: dual-mode-pipeline
tenancy: data-platform
namespace: production
dataset: enriched-orders
executionMode: batch
platformProfile: databricks
stages:
- name: acquire-orders
type: source
capability: source-acquisition
provider: spark-jdbc-source
timeout: PT10M
config:
url: jdbc:postgresql://orders-db:5432/orders
table: customer_orders
driver: org.postgresql.Driver
user: reader
password: ${DB_PASSWORD}
- name: complex-enrichment
type: transformation
capability: transformation
provider: spark-transformation
timeout: PT20M
retryPolicy:
maxAttempts: 2
backoff: PT30S
strategy: exponential
transformation:
spark:
style: dataframe
reference: com.acme.transforms.OrderEnrichment
config:
lookupTable: customer_segments
geocodingEnabled: true
sql:
style: sql
reference: transforms/order_enrichment.sql
- name: write-enriched
type: publish
capability: storage
provider: spark-file-storage
timeout: PT5M
config:
format: delta
mode: overwrite
partitionBy: order_date
policies: []
extensions: []
Key points:
sparkmode uses a custom DataFrame class for complex logic (geocoding, ML scoring)sqlmode provides a portable fallback for platforms without Spark- The runtime selects the appropriate mode based on the platform profile
- Retry policy handles transient failures in the enrichment stage
16. Pipeline with Retry Policy¶
Resilient pipeline with exponential backoff for unreliable sources.
name: resilient-api-ingest
tenancy: integrations
namespace: production
dataset: partner-data
executionMode: batch
schedule: "0 */4 * * *"
stages:
- name: fetch-partner-data
type: source
capability: source-acquisition
provider: spark-jdbc-source
timeout: PT15M
retryPolicy:
maxAttempts: 5
backoff: PT10S
strategy: exponential
config:
url: jdbc:postgresql://partner-db:5432/shared
table: partner_feed
driver: org.postgresql.Driver
user: integration_user
password: ${PARTNER_DB_PASSWORD}
connectionTimeout: 60
- name: normalise-schema
type: transformation
capability: transformation
provider: spark-transformation
timeout: PT10M
retryPolicy:
maxAttempts: 3
backoff: PT5S
strategy: exponential
transformation:
sql:
style: sql
reference: |
SELECT
COALESCE(partner_id, 'UNKNOWN') AS partner_id,
TRIM(UPPER(product_code)) AS product_code,
CAST(quantity AS INT) AS quantity,
CAST(price AS DECIMAL(10,2)) AS price,
COALESCE(currency, 'USD') AS currency,
current_timestamp() AS ingested_at
FROM {input}
- name: write-normalised
type: publish
capability: storage
provider: spark-file-storage
timeout: PT5M
retryPolicy:
maxAttempts: 3
backoff: PT5S
strategy: exponential
config:
format: parquet
mode: append
policies: []
extensions: []
Key points:
- Every stage has a retry policy — essential for unreliable external sources
- Source stage has 5 attempts with exponential backoff (10s, 20s, 40s, 80s, 160s)
connectionTimeout: 60gives the partner database time to respond- Schema normalisation handles nulls and type coercion defensively
17. Partitioned Output¶
Write with date and region partitioning for efficient query patterns.
name: partitioned-output-pipeline
tenancy: data-platform
namespace: production
dataset: regional-sales
executionMode: batch
platformProfile: databricks
schedule: "0 4 * * *"
stages:
- name: acquire-sales
type: source
capability: source-acquisition
provider: spark-file-source
timeout: PT10M
config:
path: /data/raw/daily-sales/
format: parquet
- name: add-partition-columns
type: transformation
capability: transformation
provider: spark-transformation
timeout: PT5M
transformation:
sql:
style: sql
reference: |
SELECT
*,
CAST(sale_date AS DATE) AS partition_date,
COALESCE(region, 'UNKNOWN') AS partition_region,
YEAR(sale_date) AS sale_year,
MONTH(sale_date) AS sale_month
FROM {input}
- name: write-partitioned
type: publish
capability: storage
provider: spark-file-storage
timeout: PT10M
config:
format: delta
mode: overwrite
partitionBy: sale_year,sale_month,partition_region
policies: []
extensions: []
Key points:
- Partition columns are computed in the transformation stage
- Three-level partitioning:
year/month/regionenables efficient pruning COALESCEensures no null partition values (which cause issues in Hive-style partitioning)- Delta format with overwrite replaces the full dataset daily
HOCON Examples¶
For teams using the Typesafe/Lightbend ecosystem, here are select examples in HOCON format.
Multi-Stage Pipeline in HOCON¶
name = "multi-stage-etl"
tenancy = "data-platform"
namespace = "production"
dataset = "revenue-report"
executionMode = "batch"
platformProfile = "databricks"
schedule = "0 5 * * *"
stages = [
{
name = "acquire-transactions"
type = "source"
capability = "source-acquisition"
provider = "spark-file-source"
timeout = "PT10M"
config {
path = "/data/lake/transactions/"
format = "delta"
}
},
{
name = "clean-data"
type = "transformation"
capability = "transformation"
provider = "spark-transformation"
timeout = "PT5M"
transformation {
sql {
style = "sql"
reference = """
SELECT * FROM {input}
WHERE amount IS NOT NULL AND amount > 0
"""
}
}
},
{
name = "publish-report"
type = "publish"
capability = "storage"
provider = "spark-file-storage"
timeout = "PT5M"
config {
format = "delta"
mode = "overwrite"
}
}
]
policies = []
extensions = []
Resilient Pipeline in HOCON¶
name = "resilient-ingest"
tenancy = "integrations"
namespace = "production"
dataset = "partner-data"
executionMode = "batch"
schedule = "0 */4 * * *"
stages = [
{
name = "fetch-partner-data"
type = "source"
capability = "source-acquisition"
provider = "spark-jdbc-source"
timeout = "PT15M"
retryPolicy {
maxAttempts = 5
backoff = "PT10S"
strategy = "exponential"
}
config {
url = "jdbc:postgresql://partner-db:5432/shared"
table = "partner_feed"
driver = "org.postgresql.Driver"
user = "integration_user"
password = ${PARTNER_DB_PASSWORD}
connectionTimeout = 60
}
},
{
name = "write-output"
type = "publish"
capability = "storage"
provider = "spark-file-storage"
timeout = "PT5M"
config {
format = "parquet"
mode = "append"
}
}
]
policies = []
extensions = []
HOCON variable substitution
HOCON natively supports ${VARIABLE} syntax for environment variable references. This is resolved at parse time by the Typesafe Config library.
Next Steps¶
- Writing Pipelines — Pipeline structure reference
- Stage Types — All available stage types
- Apache Spark Provider Guide — Detailed Spark configuration
- Apache Flink Provider Guide — Streaming with Flink
- Dual-Mode Transformations — Platform-portable transforms