Palantir's Pipeline Builder: Visual Orchestration of Data Pipelines
In any data-intensive organization, "moving data from A to B with transformations" sounds simple but turns into a nightmare. Here's what a typical data engineering team faces daily:
Palantir's Pipeline Builder: Visual Orchestration of Data Pipelines
“Series: S1 Palantir Decoded · Article 8 | Level: Beginner | Reading Time: 15 min
#TL;DR
- Palantir's Pipeline Builder / Transforms offers three modes (visual drag-and-drop, SQL, Python/Java code), enabling users of all skill levels to build data pipelines where every output dataset is immutable, versioned, and incrementally computable.
- Unlike dbt, Airflow, or Spark, Palantir Transforms natively integrate with the Ontology layer — pipelines don't just produce "tables," they produce business objects that Actions, Rules, and Workshop can directly consume.
- coomia-dip (ZhiCe Platform) achieves equivalent capability through PipelineService + a custom DSL + DolphinScheduler + Flink CDC, where a single line
.from_mysql().join().map_to_ontology().to_iceberg()covers the entire path from data source to Ontology.
#Introduction: Why Are Data Pipelines So Damn Hard?
In any data-intensive organization, "moving data from A to B with transformations" sounds simple but turns into a nightmare. Here's what a typical data engineering team faces daily:
Source System A (MySQL) ─→ Extract Script ─→ Staging ─→ Cleaning ─→ Wide Table
Source System B (API) ─→ Extract Script ─→ Staging ─→ Join ┘
Source System C (Files) ─→ Parse Script ─→ Staging ─→ Aggregate ─→ Report Table
↓
One day, A's schema changes
→ Everything downstream explodes
The pain points:
- Fragility: One upstream field rename breaks the entire chain
- No traceability: A number in a report is wrong — impossible to trace which step went wrong
- No rollback: Yesterday's data was overwritten by today's script — want to recover? Tough luck
- High barrier: Only people who write Spark/SQL can build pipelines — business analysts are locked out
- Disconnected from business: Pipelines produce "tables," but the business needs "objects" and "relationships"
Palantir's Pipeline Builder and Transforms were designed to solve this entire problem set.
#Part 1: Three Modes of Pipeline Builder
Palantir provides three pipeline-building modes for different roles. The core principle: one engine, multiple entry points.
#1.1 Visual Mode (Visual Pipeline Builder)
For business analysts and data product managers — pure drag-and-drop:
┌─────────────────────────────────────────────────────┐
│ Visual Pipeline Builder │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Source │───→│ Filter │───→│ Join │ │
│ │ orders │ │ status= │ │ LEFT JOIN│ │
│ │ │ │ 'active' │ │ customers│ │
│ └──────────┘ └──────────┘ └────┬─────┘ │
│ │ │
│ ┌────▼─────┐ │
│ │ Aggregate │ │
│ │ GROUP BY │ │
│ │ region │ │
│ └────┬─────┘ │
│ │ │
│ ┌────▼─────┐ │
│ │ Output │ │
│ │ regional_ │ │
│ │ summary │ │
│ └──────────┘ │
│ │
│ [Preview Data] [View Lineage] [Run] [Schedule] │
└─────────────────────────────────────────────────────┘
Every node auto-generates the corresponding Transform code. Users can "eject" from visual mode to code mode at any time to view or edit the underlying logic.
#1.2 SQL Mode
For data analysts using standard SQL (SparkSQL dialect):
-- Transform: regional_order_summary
-- Input: orders, customers
-- Output: regional_summary (versioned, incremental)
SELECT
c.region,
DATE_TRUNC('month', o.order_date) AS order_month,
COUNT(*) AS order_count,
SUM(o.amount) AS total_amount,
AVG(o.amount) AS avg_amount
FROM
orders o
LEFT JOIN customers c ON o.customer_id = c.id
WHERE
o.status = 'active'
GROUP BY
c.region,
DATE_TRUNC('month', o.order_date)
What's special about SQL mode: this isn't just a SQL query. Palantir wraps the SQL into a full Transform, automatically handling version control, incremental computation, and dependency tracking.
#1.3 Code Mode (Python / Java)
For data engineers with full flexibility:
# Palantir Foundry Transform (Python)
from transforms.api import transform, Input, Output, incremental
@transform(
orders=Input("/datasets/raw/orders"),
customers=Input("/datasets/raw/customers"),
output=Output("/datasets/clean/regional_summary"),
)
def compute(orders, customers, output):
"""
Each time this runs, the Foundry engine:
1. Checks if orders and customers have new versions
2. If yes, processes only the incremental portion
3. Produces a new immutable version
4. Automatically updates the dependency graph
"""
orders_df = orders.dataframe()
customers_df = customers.dataframe()
result = (
orders_df
.filter(orders_df.status == 'active')
.join(customers_df, orders_df.customer_id == customers_df.id, 'left')
.groupBy('region', F.date_trunc('month', 'order_date'))
.agg(
F.count('*').alias('order_count'),
F.sum('amount').alias('total_amount'),
F.avg('amount').alias('avg_amount'),
)
)
output.write_dataframe(result)
All three modes share the same execution engine and version control system. Their outputs are fully equivalent.
#Part 2: Core Transform Semantics — Immutable, Versioned, Incremental
Understanding Palantir's data pipelines isn't about "how it runs Spark." It's about three core semantic constraints on datasets.
#2.1 Immutability
In Palantir Foundry, every Transform run produces a new version rather than overwriting existing data:
Dataset: regional_summary
├── Transaction T1 (2024-01-15 08:00) ── 1,234 rows ← Version 1
├── Transaction T2 (2024-01-16 08:00) ── 1,287 rows ← Version 2
├── Transaction T3 (2024-01-17 08:00) ── 1,301 rows ← Version 3
└── Transaction T4 (2024-01-18 08:00) ── 1,298 rows ← Version 4 (current)
This means:
- Rollback: Discovered T4 has a calculation error? One-click rollback to T3
- Audit: Regulators want to know "what was this metric on 2024-01-16"? Read T2 directly
- Compare: Diff between any two versions
#2.2 Versioning and the Transaction Model
Every dataset update is wrapped in a Transaction, similar to a Git commit:
┌──────────────────────────────────────────────────┐
│ Transaction T4 │
│ │
│ Start Time: 2024-01-18 08:00:00 │
│ End Time: 2024-01-18 08:03:42 │
│ Trigger: Schedule (daily at 08:00) │
│ Input Versions: orders@T12, customers@T8 │
│ Transform: regional_summary_compute │
│ Row Delta: 1301 → 1298 (-3) │
│ Schema Delta: None │
│ Status: SUCCESS │
│ │
│ [View Input Snapshot] [View Output] [Diff Prev] │
└──────────────────────────────────────────────────┘
Key point: a Transaction precisely records "which version of inputs, through what code, produced what output." This makes every data point fully traceable.
#2.3 Incremental Computation (Incremental Transforms)
For large-scale datasets, full recomputation is too expensive. Palantir supports incremental Transforms:
@transform(
orders=Input("/datasets/raw/orders"),
output=Output("/datasets/clean/order_metrics"),
)
@incremental()
def compute_incremental(orders, output):
"""
The Foundry engine automatically tracks:
- orders was last processed at Transaction T10
- orders has new Transactions T11, T12
- Only read incremental data from T11 and T12
"""
new_orders = orders.dataframe() # Automatically contains only incremental data
metrics = new_orders.groupBy('product_id').agg(
F.sum('quantity').alias('incremental_qty')
)
# APPEND mode: append to output instead of overwrite
output.write_dataframe(metrics, mode='append')
Three incremental strategies:
| Strategy | Description | Best For |
|---|---|---|
| SNAPSHOT | Full recomputation each time | Small data, simple logic |
| APPEND | Process only new data, append to output | Log data, event streams |
| MERGE | Process new and changed data, merge into output | Dimension tables, slowly changing dimensions |
#Part 3: Dependency Graphs and Data Lineage
#3.1 Automatic Dependency Tracking
Palantir analyzes Transform Input/Output declarations to automatically build a global dependency graph:
┌───────────┐
│ raw_orders│
└─────┬─────┘
│
┌──────────────┼──────────────┐
▼ ▼ ▼
┌────────────┐ ┌────────────┐ ┌────────────┐
│clean_orders│ │order_metrics│ │order_anomaly│
└──────┬─────┘ └──────┬─────┘ └──────┬─────┘
│ │ │
▼ ▼ │
┌────────────┐ ┌────────────┐ │
│regional_ │ │product_ │ │
│summary │ │dashboard │ │
└──────┬─────┘ └────────────┘ │
│ │
▼ ▼
┌──────────────────────────────────────┐
│ ontology_order_objects │
│ (Mapped to Ontology Object Type) │
└──────────────────────────────────────┘
#3.2 Intelligent Scheduling
The dependency graph isn't just documentation — it's the foundation for scheduling:
- Auto-propagation: When
raw_ordershas new data, all downstream Transforms trigger automatically - Smart skipping: If a Transform's inputs have no new versions, skip execution
- Parallel execution: Transforms with no dependency relationship run in parallel
- Failure isolation:
order_anomalyfailing doesn't affect theclean_orderschain
#3.3 Branching Within Pipelines
Similar to Git branching, Palantir allows creating branches within data pipelines:
main branch:
raw_orders → clean_orders → regional_summary
│
│ In production
▼
Workshop Dashboard
dev branch (feature/new-cleaning-logic):
raw_orders → clean_orders_v2 → regional_summary_v2
│
│ Testing
▼
Preview / Code Review
Developers can modify Transform logic in a branch, test with real data, verify results, then merge back to main. This mechanism eliminates the risk of "experimenting on production pipelines."
#Part 4: Comparison with Mainstream Tools
#4.1 Pipeline Builder vs dbt
| Dimension | Palantir Transforms | dbt |
|---|---|---|
| Core philosophy | Pipelines within a data OS | SQL-first data transformation |
| Supported languages | Python, Java, SQL, Visual | SQL (+Jinja) |
| Version control | Built-in data versioning (Transactions) | Relies on Git + DB snapshots |
| Incremental | First-class citizen, engine-level | Via is_incremental() macro |
| Ontology integration | Native | None (pure table/view output) |
| Scheduling | Built-in intelligent scheduling | Requires external scheduler |
| Data preview | All versions previewable | Depends on DB client |
| Learning curve | Visual mode = low barrier | Requires SQL knowledge |
#4.2 Pipeline Builder vs Airflow
| Dimension | Palantir Transforms | Apache Airflow |
|---|---|---|
| Essence | Data transformation engine | Task orchestration engine |
| DAG definition | Auto-derived from I/O | Manually defined in Python |
| Data awareness | Knows data content and schema | Only knows task success/failure |
| Rollback | Data-level rollback (any version) | Must implement yourself |
| Incremental awareness | Engine-level automatic | Must implement yourself |
| Testing | Built-in data diff, branch testing | Must build test framework |
#4.3 Pipeline Builder vs Spark
Palantir's Transform engine is built on Spark, but adds critical enhancements on top:
┌──────────────────────────────────────┐
│ Palantir Transform │
│ ┌─────────────────────────────────┐ │
│ │ Versioning + Lineage + Incr. │ │
│ ├─────────────────────────────────┤ │
│ │ Security (Row/Column-level) │ │
│ ├─────────────────────────────────┤ │
│ │ Ontology Mapping Layer │ │
│ ├─────────────────────────────────┤ │
│ │ Apache Spark (Compute Engine) │ │
│ └─────────────────────────────────┘ │
└──────────────────────────────────────┘
Raw Spark solves "how to compute." Palantir Transforms solve "how to compute reliably, traceably, and collaboratively."
#Part 5: Real-World Case Study — Supply Chain Pipeline
Let's walk through a complete Pipeline Builder use case for a manufacturing company's supply chain analytics.
#5.1 Business Requirements
A global manufacturer needs real-time visibility into supply chain status and early warning of supply risks. Data comes from 5 source systems:
SAP ERP → Purchase orders, supplier master data
WMS → Warehouse inventory, in/out records
TMS → Logistics transport, in-transit inventory
IoT Hub → Factory equipment status, production progress
External → Weather forecasts, port congestion index
#5.2 Pipeline Design
SAP ──→ [Extract] ──→ raw_purchase_orders ──→ [Clean] ──→ clean_orders
WMS ──→ [Extract] ──→ raw_inventory ──→ [Clean] ──→ clean_inventory
TMS ──→ [Extract] ──→ raw_shipments ──→ [Clean] ──→ clean_shipments
IoT ──→ [Stream] ──→ raw_production ──→ [Agg] ──→ production_metrics
Ext ──→ [API] ──→ raw_external ──→ [Norm] ──→ external_risk
│ All cleaned data │
▼ ▼
┌─────────────────────────────┐
│ supply_chain_unified_view │
│ (Join, Dedup, Fill) │
└──────────────┬──────────────┘
│
┌───────────┼───────────┐
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Supplier │ │ Inventory│ │ Delivery │
│ Risk │ │ Health │ │ Forecast │
│ Score │ │ Index │ │ Model │
└────┬─────┘ └────┬─────┘ └────┬─────┘
│ │ │
▼ ▼ ▼
┌─────────────────────────────────┐
│ Ontology Object Types: │
│ Supplier, PurchaseOrder, │
│ Inventory, Shipment │
└─────────────────────────────────┘
#5.3 Code Example
@transform(
orders=Input("/supply-chain/clean/orders"),
inventory=Input("/supply-chain/clean/inventory"),
shipments=Input("/supply-chain/clean/shipments"),
external_risk=Input("/supply-chain/external/risk"),
output=Output("/supply-chain/analytics/supplier_risk_score"),
)
@incremental()
def compute_supplier_risk(orders, inventory, shipments, external_risk, output):
"""
Supplier Risk Score Transform:
- Calculate on-time delivery rate
- Calculate quality return rate
- Incorporate external risk factors
- Produce composite risk score
"""
orders_df = orders.dataframe()
shipments_df = shipments.dataframe()
risk_df = external_risk.dataframe()
# On-time delivery rate
delivery = (
orders_df.join(shipments_df, 'order_id')
.withColumn('is_late',
F.when(F.col('actual_delivery') > F.col('expected_delivery'), 1)
.otherwise(0))
.groupBy('supplier_id')
.agg(
F.avg('is_late').alias('late_rate'),
F.count('*').alias('order_count'),
)
)
# Composite score
scored = (
delivery
.join(risk_df, 'supplier_id', 'left')
.withColumn('risk_score',
F.col('late_rate') * 0.4
+ F.coalesce(F.col('external_risk_index'), F.lit(0.5)) * 0.3
+ F.coalesce(F.col('quality_defect_rate'), F.lit(0.1)) * 0.3
)
)
output.write_dataframe(scored)
#Part 6: coomia-dip Implementation — PipelineService + DSL + DolphinScheduler
coomia-dip (ZhiCe Platform), as the open-source alternative to Palantir, implements equivalent data pipeline capabilities.
#6.1 Architecture Overview
┌──────────────────────────────────────────────────────┐
│ coomia-dip Data Pipeline │
│ │
│ ┌─────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │Pipeline DSL │ │Pipeline API │ │Visual Builder│ │
│ │(Python SDK) │ │(gRPC) │ │(Web UI) │ │
│ └──────┬──────┘ └──────┬───────┘ └──────┬───────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ PipelineService (gRPC) │ │
│ │ ┌──────────┐ ┌────────────┐ ┌────────────────┐ │ │
│ │ │DAG Parser│ │Version Mgmt│ │Incremental Track│ │ │
│ │ └──────────┘ └────────────┘ └────────────────┘ │ │
│ └──────────────────────┬───────────────────────────┘ │
│ │ │
│ ┌───────────────┼───────────────┐ │
│ ▼ ▼ ▼ │
│ ┌────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │DolphinSched│ │Flink CDC │ │Spark Engine │ │
│ │(Scheduling)│ │(Real-time) │ │(Batch) │ │
│ └────────────┘ └──────────────┘ └──────────────┘ │
│ │
│ │ │
│ ▼ │
│ ┌──────────────────┐ │
│ │ Apache Iceberg │ │
│ │ (Versioned Store)│ │
│ └──────────────────┘ │
└──────────────────────────────────────────────────────┘
#6.2 Pipeline DSL: One-Liner Data Pipelines
coomia-dip's Python SDK provides an elegantly minimal Pipeline DSL:
from ontology_sdk.pipeline import PipelineBuilder
# Complete pipeline definition
pipeline = (
PipelineBuilder("supply_chain_sync")
.from_mysql(
host="erp-db.internal",
database="sap_erp",
table="purchase_orders",
cdc=True, # Enable Flink CDC real-time sync
watermark="updated_at", # Incremental watermark field
)
.join(
source="wms_inventory", # Join warehouse data
on="material_id",
how="left",
)
.filter("status IN ('OPEN', 'PARTIAL')")
.map_to_ontology(
object_type="PurchaseOrder", # Map to Ontology object
field_mapping={
"po_number": "orderId",
"vendor_id": "supplierId",
"material_id": "materialId",
"qty_ordered": "quantity",
"qty_received": "receivedQuantity",
"due_date": "expectedDelivery",
},
link_types=[
("supplierId", "Supplier", "places_order"),
("materialId", "Material", "contains"),
],
)
.to_iceberg(
table="warehouse.supply_chain.purchase_orders",
partition_by=["year(expectedDelivery)", "supplierId"],
write_mode="merge", # MERGE: insert + update
merge_key="orderId",
)
.schedule(cron="*/5 * * * *") # Every 5 minutes
.build()
)
# Deploy the pipeline
pipeline.deploy()
What happens behind this DSL:
1. from_mysql() → Creates Flink CDC Source Connector
2. join() → Generates Flink SQL JOIN statement
3. filter() → Adds WHERE condition
4. map_to_ontology() → Generates field mapping + LinkType creation rules
5. to_iceberg() → Configures Iceberg Sink + partitioning strategy
6. schedule() → Creates scheduled job in DolphinScheduler
7. build() → Compiles into an execution plan
8. deploy() → Submits to PipelineService for execution
#6.3 Versioned Storage: Iceberg Time Travel
coomia-dip leverages Apache Iceberg's Snapshot mechanism to achieve versioning equivalent to Palantir's Transaction model:
Iceberg Table: warehouse.supply_chain.purchase_orders
├── Snapshot S1 (2024-01-15 08:05) ── 12,340 rows
├── Snapshot S2 (2024-01-15 08:10) ── 12,387 rows (+47)
├── Snapshot S3 (2024-01-15 08:15) ── 12,401 rows (+14)
└── Snapshot S4 (2024-01-15 08:20) ── 12,398 rows (-3, merges)
# Time-travel queries
from ontology_sdk.data import DatasetReader
reader = DatasetReader("purchase_orders")
# Read a specific version
df_v2 = reader.as_of_snapshot(snapshot_id="S2").to_pandas()
# Read at a specific timestamp
df_yesterday = reader.as_of_timestamp("2024-01-14T23:59:59").to_pandas()
# Diff between two versions
diff = reader.diff(from_snapshot="S2", to_snapshot="S4")
print(f"Added: {diff.added_rows}, Deleted: {diff.deleted_rows}, Updated: {diff.updated_rows}")
#6.4 Real-Time Sync: The Magic of Flink CDC
For real-time data synchronization, coomia-dip uses Flink CDC instead of traditional batch extraction:
MySQL (binlog) ─────────────────────────────────┐
│
PostgreSQL (WAL) ──→ Flink CDC ──→ Transform ──→ Iceberg
Engine (Real-time) (Snapshot)
MongoDB (oplog) ────────────────────────────────┘
Comparison with traditional ETL:
| Dimension | Traditional ETL (Batch) | Flink CDC (Real-time) |
|---|---|---|
| Latency | Hours | Seconds |
| Data completeness | T+1 | Near real-time |
| Source load | High (full scan) | Low (reads binlog) |
| Schema change detection | Discovered on next run | Detected in real-time |
| Delete detection | Needs extra logic | Automatically captures DELETE |
#6.5 Scheduling and Orchestration: DolphinScheduler Integration
coomia-dip uses DolphinScheduler as its scheduling engine for enterprise-grade workflow management:
from ontology_sdk.pipeline import PipelineOrchestrator
orchestrator = PipelineOrchestrator()
# Define DAG
dag = orchestrator.create_dag(
name="daily_supply_chain_refresh",
schedule="0 6 * * *", # Daily at 6:00 AM
alert_on_failure=["ops-team@company.com"],
timeout_minutes=120,
retry_count=2,
)
# Add task nodes
t1 = dag.add_task("sync_erp", pipeline="erp_sync_pipeline")
t2 = dag.add_task("sync_wms", pipeline="wms_sync_pipeline")
t3 = dag.add_task("sync_tms", pipeline="tms_sync_pipeline")
t4 = dag.add_task("compute_unified", pipeline="unified_view_pipeline")
t5 = dag.add_task("compute_risk", pipeline="risk_score_pipeline")
t6 = dag.add_task("publish_ontology", pipeline="ontology_publish_pipeline")
# Define dependencies
t4.depends_on(t1, t2, t3) # Unified view depends on all three syncs
t5.depends_on(t4) # Risk score depends on unified view
t6.depends_on(t4, t5) # Publish depends on all computation complete
dag.deploy()
#Part 7: The "Last Mile" — Mapping to Ontology
Whether Palantir or coomia-dip, the core differentiating value of data pipelines is that the pipeline's endpoint isn't a "table" — it's an Ontology object.
#7.1 From Tables to Objects
Traditional pipeline endpoint:
source → transform → table (for humans to query with SQL)
Palantir / coomia-dip endpoint:
source → transform → Ontology Object (for Actions/Workshop/Rules to consume)
What does this difference mean in practice?
Traditional: Data engineer builds pipeline → Business user needs SQL → Finds data analyst
Ontology: Data engineer builds pipeline → Business user drags and drops in Workshop
#7.2 coomia-dip Ontology Mapping Configuration
# pipeline-config.yaml
pipeline:
name: erp_order_sync
source:
type: mysql
connection: erp-db
table: sales_orders
ontology_mapping:
object_type: SalesOrder
primary_key: order_id
properties:
- source: order_id → target: orderId (type: string)
- source: customer_id → target: customerId (type: string)
- source: order_date → target: orderDate (type: timestamp)
- source: total_amount → target: totalAmount (type: decimal)
- source: status → target: status (type: enum)
links:
- property: customerId
target_type: Customer
link_type: places_order
cardinality: many_to_one
- property: orderId
target_type: OrderItem
link_type: contains_items
cardinality: one_to_many
derived_properties:
- name: daysSinceOrder
expression: "DATEDIFF(NOW(), orderDate)"
- name: isOverdue
expression: "status = 'OPEN' AND daysSinceOrder > 30"
#Part 8: Best Practices and Pitfall Avoidance
#8.1 Pipeline Design Principles
- Single responsibility: Each Transform does one thing. Better to have many small Transforms than one giant one
- Idempotency: Every Transform must be idempotent — rerunning produces the same result
- Explicit schema declaration: Don't rely on schema inference. Explicitly declare input/output fields and types
- Test first: Test with sample data in a branch. Only merge to main after confirming correctness
#8.2 Common Mistakes
| Mistake | Consequence | Correct Approach |
|---|---|---|
| Hardcoded dates in pipeline | Backfill fails | Use parameterized time ranges |
| Ignoring NULL handling | Inaccurate aggregations | Use COALESCE or explicit NULL strategy |
| No timeout configured | One slow query blocks entire DAG | Set timeout per task |
| Skipping data validation | Dirty data enters Ontology | Add data quality assertions in Transforms |
#8.3 Performance Optimization
# Anti-pattern: read everything then filter
df = orders.dataframe() # 1 billion rows
df = df.filter(df.year == 2024) # Filter down to 10 million
# Correct pattern: leverage Iceberg partition pruning
df = orders.dataframe(
partition_filter="year = 2024" # Only reads 2024 partition
)
#Key Takeaways
- Palantir's Pipeline Builder / Transforms isn't just another ETL tool — it's a combination of a data version control system + semantic mapping engine + intelligent scheduler. The core differentiator is that pipelines produce Ontology objects, not tables.
- Immutability + Versioning + Incremental computation are the three pillars — without these three properties, data pipelines will always be fragile. Iceberg's Snapshot mechanism brings equivalent capability to the open-source world.
- coomia-dip combines Pipeline DSL + Flink CDC + DolphinScheduler + Iceberg to deliver end-to-end data pipelines from source to Ontology, where a single line
.from_mysql().join().map_to_ontology().to_iceberg()covers work that traditionally requires multiple teams and multiple tools.
#Next Article Preview
“Article 9: Palantir Contour — Enterprise Analytics Anyone Can Use
With data pipelines turning raw data into Ontology objects, the next step is enabling every business user to perform self-service analytics. Contour is Palantir's self-service analytics tool, but it's fundamentally different from Tableau/Power BI — because it analyzes Ontology objects, not tables.
#palantir #pipeline-builder #transforms #data-engineering #etl #coomia-dip #flink-cdc #iceberg #dolphinscheduler