Cosmos DB Spark Connector
Complete the full lesson to earn 25 points — 50 with Pro
Work through each section, then tap “Mark as Complete” on the last one.
✦ Skip the page breaks, the wait, and see fewer ads — read each lesson on a single page with Pro
Mastering Data Movement: The Azure Cosmos DB Spark Connector
Introduction: Why Data Movement Matters in Cosmos DB
In the modern data landscape, Azure Cosmos DB serves as the backbone for globally distributed, low-latency applications. However, a database is rarely an island. Whether you are performing complex analytical processing, migrating historical data, or synchronizing information between different storage systems, you need a reliable way to move data into and out of Cosmos DB. This is where the Azure Cosmos DB Spark Connector becomes an indispensable tool for data engineers and architects.
The Spark Connector acts as a bridge between the distributed computing power of Apache Spark—whether running on Azure Databricks, HDInsight, or an open-source Spark cluster—and the globally replicated environment of Cosmos DB. By using this connector, you can treat Cosmos DB as a high-performance data sink or source, enabling you to run large-scale ETL (Extract, Transform, Load) pipelines that would be impossible to manage via standard API calls or individual document inserts.
Understanding how to effectively use the Spark Connector is critical for maintaining performance and cost-efficiency. If configured incorrectly, data movement tasks can overwhelm your Request Units (RUs) or lead to significant latency in your production applications. This lesson will guide you through the architecture, implementation, optimization, and best practices required to master data movement using the Cosmos DB Spark Connector.
Understanding the Architecture of the Spark Connector
At its core, the Azure Cosmos DB Spark Connector leverages the Cosmos DB change feed and the Spark distributed processing model. When reading data, the connector partitions the collection based on the physical partitions of the Cosmos DB container. This allows multiple Spark executors to read data in parallel, drastically reducing the time required to ingest large datasets.
When writing data, the connector translates Spark DataFrames into batches of documents. It handles the complexities of retries, throttling, and partition key management, ensuring that your data lands in the correct physical partition without requiring you to manually manage the underlying sharding logic. This abstraction is powerful because it allows you to focus on the data transformation logic rather than the low-level mechanics of document storage.
Key Components of the Connector
- The Partitioning Strategy: The connector automatically discovers the physical partitions of your Cosmos DB container. By aligning Spark partitions with these physical partitions, the connector minimizes cross-partition traffic.
- The Change Feed Integration: When reading, the connector can be configured to consume the change feed. This is essential for streaming pipelines where you need to process updates in near real-time rather than performing a full bulk export.
- Write Batching: The connector groups documents into batches before sending them to the Cosmos DB endpoint. This is a critical optimization that reduces the number of network round-trips and helps you stay within your provisioned throughput limits.
Callout: Spark Connector vs. Bulk Executor While the Bulk Executor library was historically used for high-performance writes, the modern Spark Connector incorporates these bulk capabilities natively. You should prefer the Spark Connector for any ETL or data movement task involving Spark, as it provides a higher-level API, better integration with Spark SQL, and improved support for schema evolution.
Getting Started: Setting Up Your Environment
To begin moving data, you must ensure your environment is correctly configured. The Spark Connector is distributed as a library that you add to your Spark cluster. Depending on your platform—Azure Databricks or a standalone Spark cluster—the installation method varies, but the dependency remains the same.
Prerequisites
- Azure Cosmos DB Account: You need the endpoint URI and the Primary Key or Read-Only Key.
- Spark Cluster: A running Spark cluster with access to the internet or a VNet peering to the Cosmos DB instance.
- Maven Coordinates: You must include the
azure-cosmos-sparklibrary.
For Azure Databricks, you can add the library by navigating to the "Libraries" tab in your cluster configuration and selecting "Maven." Search for com.azure.cosmos.spark:azure-cosmos-spark-3-4_2-12 (ensure you match the version to your Spark and Scala version).
Reading Data from Cosmos DB
Reading data is the first step in most data movement workflows. The connector allows you to read data using both batch and streaming modes. Batch mode is ideal for one-time migrations or daily snapshots, while streaming mode is designed for continuous data processing.
Batch Reading Example
In batch mode, you define the connection configuration and then read the container as a DataFrame.
// Define the configuration map
val cosmosConfig = Map(
"spark.cosmos.accountEndpoint" -> "https://your-account.documents.azure.com:443/",
"spark.cosmos.accountKey" -> "your-primary-key",
"spark.cosmos.database" -> "YourDatabase",
"spark.cosmos.container" -> "YourContainer"
)
// Read the data into a DataFrame
val df = spark.read.format("cosmos.oltp").options(cosmosConfig).load()
// Perform transformations
val processedDf = df.filter($"status" === "active").select("id", "payload")
// Show the results
processedDf.show()
Streaming Reading Example
Streaming is more complex but provides the ability to react to data changes. By setting the spark.cosmos.read.changeFeed.enabled option, you can create a structured stream that consumes the change feed.
val streamingDf = spark.readStream
.format("cosmos.oltp")
.options(cosmosConfig)
.option("spark.cosmos.read.changeFeed.enabled", "true")
.load()
// Write to a console sink for testing
val query = streamingDf.writeStream
.format("console")
.start()
Note: When using the change feed, ensure you have a "lease" container defined. The connector uses this container to keep track of the progress of your stream, allowing it to resume from where it left off in case of cluster failure.
Writing Data to Cosmos DB
Writing data is where most performance issues arise. If you attempt to write too many documents per second without proper batching or throughput, you will encounter 429 Too Many Requests errors. The connector includes built-in mechanisms to handle these scenarios, but you must configure them correctly.
Best Practices for Writing Data
- Optimize Batch Size: The
spark.cosmos.write.bulk.maxConcurrentCosmosPartitionsandspark.cosmos.write.batchSizesettings dictate how much data is sent in a single burst. Start with default settings and increase them only if you have sufficient RU headroom. - Handle Idempotency: Ensure that your Spark jobs are idempotent. If a job fails halfway through, you should be able to restart it without creating duplicate documents. Using the
idfield consistently is the best way to achieve this. - Partition Key Awareness: When writing data, the connector uses the partition key defined in your Spark DataFrame. If your DataFrame lacks the partition key, the connector will have to perform a cross-partition write, which is significantly slower and more expensive.
Writing Code Example
val data = Seq(("1", "Alice", "Sales"), ("2", "Bob", "Engineering")).toDF("id", "name", "department")
data.write.format("cosmos.oltp")
.options(cosmosConfig)
.option("spark.cosmos.write.strategy", "ItemOverwrite")
.mode("append")
.save()
Warning: Using
ItemOverwriteis a powerful way to handle data updates, but be cautious. If your Spark DataFrame does not contain the full document structure, you might accidentally overwrite an existing document with a partial one. Always ensure you are writing the full, intended state of the document.
Performance Tuning and Common Pitfalls
Data movement efficiency is often the difference between a successful project and a budget overrun. Cosmos DB is billed based on throughput (Request Units), and inefficient Spark jobs can consume your RUs rapidly.
Tuning Parameters
spark.cosmos.read.partitioning.strategy: By default, this is set toDefault. If you find your reads are skewed, you can experiment withCustomstrategies to better distribute the load.spark.cosmos.write.bulk.enabled: Always keep this enabled for high-volume writes. It is the most effective way to utilize provisioned throughput.spark.cosmos.read.maxItemCount: This controls the number of items returned in a single response from the backend. Increasing this can improve read throughput but will increase the memory pressure on your Spark executors.
Common Pitfalls
- Ignoring RU Limits: If your Spark job consumes all your RUs, your production applications will experience latency. Always consider using Autoscale throughput on your Cosmos DB containers during large data movement tasks.
- Large Document Sizes: Cosmos DB has a 2MB limit per document. If your Spark transformation creates documents larger than this, the write will fail. Always validate your schema before writing.
- Unindexed Fields: If you are filtering data during the read process using fields that are not indexed in Cosmos DB, the query will result in a full collection scan, which is extremely expensive and slow.
| Feature | Batch Mode | Streaming Mode |
|---|---|---|
| Use Case | One-time migrations, bulk loads | Real-time analytics, event processing |
| Performance | High throughput, higher latency | Low latency, continuous load |
| Checkpointing | Not required | Required (Lease container) |
| Complexity | Low | Medium/High |
Handling Schema Evolution
In many real-world scenarios, the structure of your data changes over time. You might add new fields to your application, and consequently, your Cosmos DB documents. The Spark Connector is generally flexible, but you must be prepared to handle schema mismatches.
When reading from Cosmos DB, Spark infers the schema. If you have documents with varying schemas, Spark might produce a StructType that includes all possible fields, with missing fields represented as null. This is usually acceptable, but it can lead to issues if you try to write this data back to a system that requires a strict schema (like a SQL database).
To handle schema evolution gracefully, you can explicitly define the schema in your Spark job. This forces Spark to ignore unexpected fields or fail early if the data doesn't match your expectations, providing a safety net for your data pipelines.
import org.apache.spark.sql.types._
val schema = StructType(Array(
StructField("id", StringType, false),
StructField("name", StringType, true),
StructField("version", IntegerType, true)
))
val df = spark.read.schema(schema).format("cosmos.oltp").options(cosmosConfig).load()
Advanced Data Movement: Multi-Region Writes
If your Cosmos DB account is configured for multi-region writes, your Spark Connector can take advantage of this to reduce latency and improve availability. By default, the connector will attempt to write to the local region. However, you can influence this behavior by setting the spark.cosmos.preferredRegions option.
This is particularly useful if you have a Spark cluster running in a specific Azure region and you want to ensure that it writes to the nearest Cosmos DB replica. By minimizing the network distance between the Spark driver/executors and the Cosmos DB endpoint, you can significantly improve the performance of your data movement operations.
Configuration for Multi-Region
val multiRegionConfig = cosmosConfig + (
"spark.cosmos.preferredRegions" -> "East US,West US"
)
Callout: The Importance of Locality Data movement is inherently network-bound. Even with the best connector, if your Spark cluster is in a different continent than your Cosmos DB account, your performance will suffer due to the speed of light constraints on network round-trips. Always aim to deploy your Spark clusters in the same Azure region as your primary Cosmos DB replica whenever possible.
Security and Compliance
When moving data, security is paramount. You are essentially creating a pipeline that might contain sensitive customer information. The Cosmos DB Spark Connector supports several security features that you should implement as part of your standard operating procedure.
- Authentication: Never hardcode your keys in your Spark notebooks. Use Azure Key Vault to store your Cosmos DB primary keys and retrieve them at runtime using the
dbutils.secrets.getutility in Databricks or equivalent secret management tools. - Network Isolation: Use Private Links to ensure that your data movement traffic never traverses the public internet. By configuring your Spark cluster and Cosmos DB to use a Private Endpoint, you keep your data entirely within the Microsoft backbone network.
- Encryption: Ensure that your Spark cluster is configured with encryption at rest and in transit. Cosmos DB handles encryption at rest automatically, but you should verify that your Spark cluster's temporary storage (where shuffle data resides) is also encrypted.
Example: Retrieving Keys from Key Vault
val accountKey = dbutils.secrets.get(scope = "my-key-vault", key = "cosmos-key")
val secureConfig = Map(
"spark.cosmos.accountEndpoint" -> "https://your-account.documents.azure.com:443/",
"spark.cosmos.accountKey" -> accountKey,
// ... other settings
)
Troubleshooting Common Errors
Even with perfect planning, you will eventually encounter errors. Understanding how to interpret them is the hallmark of an expert.
429 Request Rate Too Large: This is the most common error. It means your Spark job is pushing harder than the provisioned throughput allows.- Fix: Implement a retry policy in your application, or increase the provisioned RUs on the container.
408 Request Timeout: This occurs when the server is taking too long to respond.- Fix: Check for network congestion or complex queries that are taking too long to execute.
413 Request Entity Too Large: Your document exceeds the 2MB limit.- Fix: Break your documents into smaller chunks or use a different storage mechanism for large blobs (like Azure Blob Storage), storing only the reference in Cosmos DB.
Spark Job Failure due to OutOfMemory: Your Spark executors are running out of memory.- Fix: Increase the executor memory or decrease the batch size to reduce the number of documents held in memory at any given time.
Best Practices Checklist for Production
To ensure your data movement pipelines are stable, perform the following checks before promoting your job to production:
- Monitor RU Consumption: Use Azure Monitor to track the "Total Requests" and "Throttled Requests" metrics during your test runs.
- Test with Representative Data: Do not test with 10 documents. Test with a volume that represents at least 10-20% of your production load to identify performance bottlenecks.
- Use Automated Retries: Ensure your Spark jobs are configured with appropriate retry logic, especially when dealing with transient network errors.
- Implement Logging: Log the number of documents read and written per task. This will help you identify skewed partitions where one task is doing significantly more work than others.
- Clean Up Resources: If you are using temporary containers for staging data, ensure your scripts include a cleanup step to delete them once the data movement is complete.
Summary and Key Takeaways
Mastering the Azure Cosmos DB Spark Connector is a journey of understanding how distributed systems interact with specialized storage engines. By leveraging the parallel processing capabilities of Spark, you can move massive amounts of data efficiently, provided you respect the underlying throughput and partitioning constraints of Cosmos DB.
Key Takeaways:
- Parallelism is Key: The connector is designed for distributed operations. Always ensure your Spark partitions align with your Cosmos DB physical partitions to maximize performance.
- Throughput Management: Be mindful of Request Units (RUs). Use bulk writing and batching to optimize throughput consumption and avoid throttling.
- Idempotency Matters: Design your data movement pipelines to be idempotent. This allows you to handle failures gracefully without risking data corruption or duplication.
- Security First: Always use secret management for your connection strings and prioritize private networking to keep your data secure during transit.
- Monitor and Tune: Data movement is not "set it and forget it." Continuously monitor your RU usage and Spark executor performance to ensure your pipelines remain efficient as your data volume grows.
- Streaming vs. Batch: Choose the right tool for the job. Use batch processing for bulk migrations and streaming for real-time integration.
- Schema Awareness: Be prepared for schema evolution by defining explicit schemas where possible and handling potential nulls or unexpected fields in your transformation logic.
By applying these principles, you will be able to build robust, scalable, and secure data pipelines that leverage the full power of Azure Cosmos DB and Apache Spark. Whether you are performing a simple migration or building a complex real-time analytics engine, these practices will serve as the foundation for your success.
Reach the last section to complete this lesson and earn points — you're on section 1 of 12.
- Introduction to Cosmos DB Data Modeling
- Introduction to Cosmos DB Data Modeling Quiz5q
- Multiple Entity Types in Same Container
- Multiple Entity Types in Same Container Quiz5q
- Storing Related Entities in Same Document
- Storing Related Entities in Same Document Quiz5q
- Denormalizing Data Across Documents
- Denormalizing Data Across Documents Quiz5q
- Referencing Between Documents
- Referencing Between Documents Quiz5q
- Partition Keys and Document IDs
- Partition Keys and Document IDs Quiz5q
- Time to Live (TTL) Configuration
- Time to Live (TTL) Configuration Quiz5q
- Document Versioning Strategies
- Document Versioning Strategies Quiz5q
- Schema Versioning Patterns
- Schema Versioning Patterns Quiz5q
- Choosing Partition Strategies
- Choosing Partition Strategies Quiz5q
- Partition Key Selection Best Practices
- Partition Key Selection Best Practices Quiz5q
- Transactions and Partition Keys
- Transactions and Partition Keys Quiz5q
- Cross-Partition Query Costs
- Cross-Partition Query Costs Quiz5q
- Data Distribution Analysis
- Data Distribution Analysis Quiz5q
- Throughput Distribution Planning
- Throughput Distribution Planning Quiz5q
- Synthetic Partition Keys
- Synthetic Partition Keys Quiz5q
- Hierarchical Partition Keys
- Hierarchical Partition Keys Quiz5q
- Throughput and Storage Requirements
- Throughput and Storage Requirements Quiz5q
- Serverless vs Provisioned Throughput
- Serverless vs Provisioned Throughput Quiz5q
- Database-Level Provisioned Throughput
- Database-Level Provisioned Throughput Quiz5q
- Granular Scale Units
- Granular Scale Units Quiz5q
- Global Distribution Costs
- Global Distribution Costs Quiz5q
- Configuring Throughput in Portal
- Configuring Throughput in Portal Quiz5q
- Gateway vs Direct Connectivity Mode
- Gateway vs Direct Connectivity Mode Quiz5q
- Creating Database Connections
- Creating Database Connections Quiz5q
- Azure Cosmos DB Emulator
- Azure Cosmos DB Emulator Quiz5q
- Connection Error Handling
- Connection Error Handling Quiz5q
- Singleton Pattern for Clients
- Singleton Pattern for Clients Quiz5q
- Global Distribution Regions
- Global Distribution Regions Quiz5q
- Threading and Parallelism
- Threading and Parallelism Quiz5q
- Arrays and Nested Objects Queries
- Arrays and Nested Objects Queries Quiz5q
- Correlated Subqueries
- Correlated Subqueries Quiz5q
- Array and Type-Checking Functions
- Array and Type-Checking Functions Quiz5q
- Mathematical and String Functions
- Mathematical and String Functions Quiz5q
- Date Functions in Queries
- Date Functions in Queries Quiz5q
- Point Operations vs Query Operations
- Point Operations vs Query Operations Quiz5q
- CRUD Point Operations
- CRUD Point Operations Quiz5q
- Patch Operations for Updates
- Patch Operations for Updates Quiz5q
- Transactional Batch Operations
- Transactional Batch Operations Quiz5q
- Bulk Operations with SDK
- Bulk Operations with SDK Quiz5q
- Optimistic Concurrency with ETags
- Optimistic Concurrency with ETags Quiz5q
- Query Pagination and Continuation
- Query Pagination and Continuation Quiz5q
- Cosmos DB Mirroring for Fabric
- Cosmos DB Mirroring for Fabric Quiz5q
- Mirroring vs Spark Connector
- Mirroring vs Spark Connector Quiz5q
- Enabling Analytical Store
- Enabling Analytical Store Quiz5q
- Synapse Spark and SQL Queries
- Synapse Spark and SQL Queries Quiz5q
- Change Data Capture in Analytical Store
- Change Data Capture in Analytical Store Quiz5q
- Azure Functions and Event Hubs Integration
- Azure Functions and Event Hubs Integration Quiz5q
- Denormalization with Change Feed
- Denormalization with Change Feed Quiz5q
- Referential Integrity with Change Feed
- Referential Integrity with Change Feed Quiz5q
- Azure AI Search Integration
- Azure AI Search Integration Quiz5q
- Azure Functions Change Feed Trigger
- Azure Functions Change Feed Trigger Quiz5q
- Consuming Change Feed with SDK
- Consuming Change Feed with SDK Quiz5q
- Change Feed Estimator
- Change Feed Estimator Quiz5q
- Denormalization via Change Feed
- Denormalization via Change Feed Quiz5q
- Aggregation Persistence with Change Feed
- Aggregation Persistence with Change Feed Quiz5q
- Read-Heavy vs Write-Heavy Indexing
- Read-Heavy vs Write-Heavy Indexing Quiz5q
- Index Type Selection
- Index Type Selection Quiz5q
- Custom Indexing Policies
- Custom Indexing Policies Quiz5q
- Composite Index Implementation
- Composite Index Implementation Quiz5q
- Index Performance Optimization
- Index Performance Optimization Quiz5q
- Response Status Codes and Metrics
- Response Status Codes and Metrics Quiz5q
- Normalized RU Consumption Monitoring
- Normalized RU Consumption Monitoring Quiz5q
- Server-Side Latency Metrics
- Server-Side Latency Metrics Quiz5q
- Data Replication Monitoring
- Data Replication Monitoring Quiz5q
- Azure Monitor Alerts Configuration
- Azure Monitor Alerts Configuration Quiz5q
- Resource Logs Implementation
- Resource Logs Implementation Quiz5q
- Partition Throughput Monitoring
- Partition Throughput Monitoring Quiz5q
- Encryption Key Management
- Encryption Key Management Quiz5q
- Network-Level Access Control
- Network-Level Access Control Quiz5q
- Data Encryption Configuration
- Data Encryption Configuration Quiz5q
- Azure RBAC for Control Plane
- Azure RBAC for Control Plane Quiz5q
- Microsoft Entra ID for Data Plane
- Microsoft Entra ID for Data Plane Quiz5q
- CORS Settings Configuration
- CORS Settings Configuration Quiz5q
- Customer-Managed Keys
- Customer-Managed Keys Quiz5q
- Always Encrypted Implementation
- Always Encrypted Implementation Quiz5q
- Data Movement Strategy Selection
- Data Movement Strategy Selection Quiz5q
- SDK Bulk Operations for Data Movement
- SDK Bulk Operations for Data Movement Quiz5q
- Azure Data Factory Pipelines
- Azure Data Factory Pipelines Quiz5q
- Kafka Connector Integration
- Kafka Connector Integration Quiz5q
- Azure Stream Analytics Integration
- Azure Stream Analytics Integration Quiz5q
- Cosmos DB Spark Connector
- Cosmos DB Spark Connector Quiz5q
Enjoying the courses?
Everything stays free. Pro shows fewer ads, doubles the points you earn on every lesson and quiz so you progress twice as fast, unlocks half of every practice exam — plus full case studies — with the Learn & Exam study modes, and lets you read each lesson on one page.
- ✓ Fewer advertisements
- ✓ 2× points per lesson & quiz
- ✓ 50% of every exam unlocked
- ✓ Learn & Exam modes
- ✓ Distraction-free lessons