NoSQL for Big Data
Cassandra, MongoDB, and HBase at scale
Scaling Beyond Relational Databases
When your data grows to billions of records, traditional relational databases hit their limits. NoSQL databases like Cassandra, MongoDB, and HBase are designed from the ground up for massive scale, handling petabytes of data across hundreds of servers. They sacrifice some traditional database features (like complex joins and strict consistency) for horizontal scalability, high availability, and performance. Understanding when and how to use each is critical for building systems that can handle internet-scale workloads.
What Qualifies as "Big Data"?
Big Data isn't just about size, it's about the 3 V's (or 5 V's):
π Volume
Terabytes to petabytes of data, too large for single server
β‘ Velocity
High-speed data streams, millions of writes per second
π Variety
Structured, semi-structured, unstructured, many data types
β Veracity
Quality and trustworthiness of data varies
π° Value
Extracting business value from massive datasets
CAP Theorem: Choose Two
In distributed systems, you can only guarantee two of three properties:
Consistency
All nodes see the same data at the same time
Availability
Every request gets a response (success/failure)
Partition Tolerance
System works despite network failures
| Database | CAP Choice | Trade-off |
|---|---|---|
| Cassandra | AP (Availability + Partition) | Eventually consistent (tunable) |
| MongoDB | CP (Consistency + Partition) | May sacrifice availability during partition |
| HBase | CP (Consistency + Partition) | Strong consistency, regions may be unavailable |
Apache Cassandra
Write-optimized, masterless architecture
Cassandra is a wide-column store designed for massive write throughput and linear scalability. With no single point of failure and masterless architecture, it's perfect for time-series data, IoT, and applications that need to write millions of events per second.
Key Characteristics
π Masterless Architecture
All nodes are equal, no master/slave. Any node can handle any request.
π Linear Scalability
Double your nodes = double your throughput. Scales horizontally to 1000+ nodes.
βοΈ Tunable Consistency
Choose consistency level per query: ONE, QUORUM, ALL
βοΈ Write-Optimized
Optimized for writes, uses log-structured storage, extremely fast inserts
Data Model: Query-First Design
Unlike relational databases, you design Cassandra tables around your queries, not entities.
-- Create keyspace (like database)
CREATE KEYSPACE ecommerce
WITH replication = {
'class': 'NetworkTopologyStrategy',
'datacenter1': 3, -- 3 replicas in DC1
'datacenter2': 2 -- 2 replicas in DC2
};
-- Create table (design for specific query!)
CREATE TABLE user_activity_by_date (
user_id UUID,
activity_date DATE,
activity_time TIMESTAMP,
action TEXT,
details MAP<TEXT, TEXT>,
PRIMARY KEY ((user_id, activity_date), activity_time)
) WITH CLUSTERING ORDER BY (activity_time DESC);Partition key: (user_id, activity_date), groups data by user and date
Clustering key: activity_time, sorts within partition (descending)
Example: Writing Data
-- Insert (extremely fast, just append to log)
INSERT INTO user_activity_by_date (
user_id, activity_date, activity_time, action, details
) VALUES (
uuid(),
'2024-01-15',
toTimestamp(now()),
'page_view',
{'page': '/products', 'duration_sec': '45'}
);Written in ~1ms (log-structured, no locks)
Replicated to 3 nodes asynchronously
Example: Efficient Query
-- Query by partition key (FAST, single partition) SELECT * FROM user_activity_by_date WHERE user_id = 550e8400-e29b-41d4-a716-446655440000 AND activity_date = '2024-01-15' LIMIT 100;
Returns 100 most recent activities for user on Jan 15
Query hits 1 partition on 1-3 nodes (milliseconds)
Example: Inefficient Query (Anti-Pattern)
-- BAD: Query without partition key SELECT * FROM user_activity_by_date WHERE action = 'purchase'; -- Scans ALL partitions!
β Full cluster scan, touches every node
β Extremely slow on large datasets
Solution: Create a separate table indexed by action
Consistency Levels
ONE
Wait for 1 replica to respond
Fastest, least consistentQUORUM
Wait for majority (RF/2 + 1)
Balanced (most common)ALL
Wait for all replicas
Slowest, strongest consistencyWhen to Use Cassandra
- Time-series data (IoT sensors, logs, metrics)
- High write throughput requirements (millions/sec)
- Need linear scalability to 1000+ nodes
- Multi-datacenter deployments
- Messaging/social media feeds
- Event logging and click streams
Pros & Cons
β Pros
- Linear scalability (proven to 1000+ nodes)
- No single point of failure
- Extremely fast writes
- Multi-datacenter replication built-in
- Tunable consistency
- Handles petabytes of data
β Cons
- No joins or aggregations
- Must design tables per query (data duplication)
- Eventually consistent by default
- Complex operational overhead
- Steep learning curve
- Poor for ad-hoc queries
MongoDB
Document database with rich queries
MongoDB stores data as flexible JSON-like documents with dynamic schemas. It's developer-friendly with a rich query language, supports sharding for horizontal scaling, and provides ACID transactions. Popular for web applications, content management, and rapid development.
Key Characteristics
π Document Model
Flexible JSON documents, each can have different fields
π Rich Queries
Powerful query language with aggregation pipeline, text search
π Sharding
Automatic horizontal partitioning across servers
π ACID Transactions
Multi-document ACID transactions (since v4.0)
Architecture: Replica Sets + Sharding
ββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β SHARDED CLUSTER β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β ββββββββββββββββ ββββββββββββββββ βββββββββββββ β
β β Shard 1 β β Shard 2 β β Shard 3 β β
β β (Replica Set)β β (Replica Set)β β(Replica...β β
β β β β β β β β
β β ββββββββββββ β β ββββββββββββ β βββββββββββββ β
β β β Primary β β β β Primary β β ββPrimary ββ β
β β ββββββββββββ β β ββββββββββββ β βββββββββββββ β
β β ββββββββββββ β β ββββββββββββ β βββββββββββββ β
β β βSecondary β β β βSecondary β β ββSecondaryββ β
β β ββββββββββββ β β ββββββββββββ β βββββββββββββ β
β ββββββββββββββββ ββββββββββββββββ βββββββββββββ β
β β² β² β² β
βββββββββββΌβββββββββββββββββΌβββββββββββββββββΌβββββββββ
ββββββββββββββββββΌβββββββββββββββββ
β
ββββββββΌβββββββ
β mongos β
β (Router) β
βββββββββββββββExample: Flexible Schema
// Insert documents with different structures
db.products.insertMany([
{
name: "Laptop",
price: 999,
specs: {cpu: "Intel i7", ram: "16GB"},
tags: ["electronics", "computers"]
},
{
name: "T-Shirt",
price: 25,
size: "L",
color: "blue",
tags: ["clothing"]
// Different fields, no problem!
}
]);2 documents inserted with different schemas
No migrations needed, schema-less flexibility
Example: Rich Queries
// Complex query with operators
db.products.find({
price: { $gte: 100, $lte: 2000 },
tags: { $in: ["electronics", "computers"] },
"specs.ram": { $exists: true }
}).sort({ price: -1 }).limit(10);Returns top 10 electronics with RAM between $100-$2000
Sorted by price descending, all in one query
Example: Aggregation Pipeline
// Analytics: Average price by category
db.products.aggregate([
{ $match: { price: { $gt: 0 } } },
{ $group: {
_id: "$category",
avgPrice: { $avg: "$price" },
count: { $sum: 1 }
}
},
{ $sort: { avgPrice: -1 } }
]);[ { _id: "Electronics", avgPrice: 750, count: 45 }, { _id: "Clothing", avgPrice: 35, count: 120 } ]
Sharding Strategy
// Enable sharding on database
sh.enableSharding("ecommerce");
// Shard collection by user_id (hashed for even distribution)
sh.shardCollection(
"ecommerce.orders",
{ user_id: "hashed" }
);
// Result: Orders distributed evenly across shards
// Queries for specific user_id route to single shardData automatically partitioned across shards
Horizontal scaling achieved, add shards as data grows
When to Use MongoDB
- Rapid application development (flexible schema)
- Content management systems
- Catalogs with varied product types
- Real-time analytics with aggregation pipeline
- Mobile apps with offline sync
- When you need both scale AND rich queries
Pros & Cons
β Pros
- Developer-friendly (JSON, no schema)
- Rich query language
- Powerful aggregation framework
- ACID transactions
- Horizontal scaling via sharding
- Strong community and tooling
β Cons
- Memory intensive (indexes in RAM)
- Data duplication with embedded docs
- Sharding complexity for large clusters
- Not ideal for complex joins
- Can be overkill for simple use cases
- Write amplification with indexes
Apache HBase
Hadoop's column-family database for sparse data
HBase is Google Bigtable's open-source implementation, built on top of Hadoop HDFS. It excels at storing billions of rows with millions of columns per row, perfect for wide, sparse datasets. Strong consistency and tight Hadoop integration make it ideal for big data analytics pipelines.
Key Characteristics
π Column-Family Store
Billions of rows, millions of columns, extremely sparse
π Hadoop Integration
Built on HDFS, tight integration with MapReduce, Spark
π― Strong Consistency
CP in CAP, always consistent reads/writes
β±οΈ Versioned Data
Automatic timestamping, keeps multiple versions of cells
Architecture: Regions and RegionServers
βββββββββββββββββββββββββββββββββββββββββββββββββββββ
β HBase CLUSTER β
βββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β βββββββββββββββ βββββββββββββββ ββββββββββββββ β
β βRegionServer1β βRegionServer2β βRegionServerβ β
β β β β β β β β
β β Region A β β Region B β β Region C β β
β β (rows 0-100)β β(rows 101-200β β(rows 201+) β β
β β β β β β β β
β β MemStore β β MemStore β β MemStore β β
β β HFile β β HFile β β HFile β β
β βββββββββββββββ βββββββββββββββ ββββββββββββββ β
β β² β² β² β
βββββββββββΌβββββββββββββββββΌβββββββββββββββββΌββββββββ
β β β
ββββββββββββββββββΌβββββββββββββββββ
β
ββββββββΌβββββββ
β Master β
β (metadata) β
βββββββββββββββ
β
βββββββββΌβββββββββ
β ZooKeeper β
β (coordination) β
ββββββββββββββββββRegions automatically split and rebalanced
Data Model: Row Key Design is Critical
# Create table with Column Families (CF)
create 'web_analytics',
{NAME => 'user_info', VERSIONS => 3},
{NAME => 'page_views', VERSIONS => 1}
# Key Strategy: Reverse Timestamp RowKey
# RowKey = [user_id] + [Long.MAX_VALUE - timestamp]Row key determines data locality and scan efficiency
Column families group related columns (stored together)
Example: Writing Data
// Put data (Java API)
Put put = new Put(Bytes.toBytes("user123_99999984321")); // RowKey
// Column Family : Qualifier : Value
put.addColumn(CF_INFO, Bytes.toBytes("name"), Bytes.toBytes("Alice"));
put.addColumn(CF_VIEWS, Bytes.toBytes("/products"), Bytes.toBytes("5"));
table.put(put);Data written to MemStore (in-memory)
Flushed to HFile on HDFS periodically
Strong consistency guaranteed
ββββββββββββββββββββββββ¬ββββββββββββ¬βββββββββββββββ¬ββββββββββ β RowKey β CF:Family β CF:Qualifier β Value β ββββββββββββββββββββββββΌββββββββββββΌβββββββββββββββΌββββββββββ€ β user123_99999984321 β user_info β name β Alice β β user123_99999984321 β page_viewsβ /products β 5 β ββββββββββββββββββββββββ΄ββββββββββββ΄βββββββββββββββ΄ββββββββββ
Example: Scanning Data
// Scan range of rows (user's recent activity)
Scan scan = new Scan();
scan.withStartRow(Bytes.toBytes("user123_999999999999000"));
scan.withStopRow(Bytes.toBytes("user123_999999999999999"));
scan.addFamily(Bytes.toBytes("page_views"));
ResultScanner scanner = table.getScanner(scan);
for (Result result : scanner) {
// Process results
}Efficient range scan, data is co-located by row key
Returns all page_view data for user in time range
Example: Versioning
// Get multiple versions of a cell
Get get = new Get(Bytes.toBytes("user123"));
get.addColumn(Bytes.toBytes("user_info"), Bytes.toBytes("email"));
get.setMaxVersions(3); // Get last 3 versions
Result result = table.get(get);
List<Cell> cells = result.getColumnCells(...);
// Returns 3 timestamped versions of email[ { timestamp: 1704067200000, value: "alice@new.com" }, { timestamp: 1704063600000, value: "alice@old.com" }, { timestamp: 1704060000000, value: "alice@original.com" } ]
When to Use HBase
- Massive datasets (100TB+) with sparse columns
- Need Hadoop ecosystem integration
- Time-series data with historical versioning
- Sequential reads/writes by row key
- Strong consistency required
- Search engine indexing, web crawling
Pros & Cons
β Pros
- Handles billions of rows effortlessly
- Strong consistency (CP)
- Perfect for sparse, wide tables
- Tight Hadoop integration
- Automatic versioning
- Battle-tested at scale
β Cons
- Complex setup (HDFS, ZooKeeper)
- Requires Java knowledge
- Row key design critical (can't change)
- No secondary indexes (limited queries)
- Heavy operational overhead
- Overkill for small datasets
Side-by-Side Comparison
| Feature | Cassandra | MongoDB | HBase |
|---|---|---|---|
| Data Model | Wide-column store | Document (JSON) | Column-family |
| CAP Theorem | AP (tunable) | CP | CP |
| Consistency | Eventually consistent | Strong (primary reads) | Strong |
| Query Language | CQL (SQL-like) | Rich query API | Key-based + scans |
| Transactions | Lightweight (no multi-row) | Multi-document ACID | Row-level only |
| Scalability | Linear (1000+ nodes) | Sharding (100s nodes) | 100s of nodes |
| Best For | Time-series, IoT, writes | Web apps, CMS, flexible | Hadoop, sparse, versioned |
| Learning Curve | Steep | Easy | Very steep |
Best Practices for NoSQL at Scale
Unlike relational databases where you normalize first and query later, NoSQL requires understanding your queries BEFORE designing tables.
β Do:
- List all queries your app will make
- Create separate tables for different access patterns (denormalize)
- Design partition/shard keys that align with queries
- Accept data duplication as a trade-off for performance
β Don't:
- Try to normalize data like in SQL
- Design tables around entities instead of queries
- Expect to support ad-hoc queries efficiently
Your partition key determines data distribution and query performance. A bad key = hot spots and slow queries.
β Good Keys
- user_id (evenly distributed)
- device_id (IoT data)
- hashed(email) (uniform)
- Composite: (user_id, date)
β Bad Keys
- timestamp (all writes hit same partition)
- status ("active" gets all traffic)
- country (uneven distribution)
- Sequential IDs (hot spots)
NoSQL databases require active monitoring, problems often appear only at scale.
Key Metrics to Watch:
- Read/Write latency, Spikes indicate problems
- CPU and memory per node, Hot spots?
- Compaction lag (Cassandra/HBase), Affects reads
- Replication lag, Consistency issues
- Disk usage per node, Unbalanced?
Data that never expires will eventually fill your cluster. Implement time-to-live (TTL) policies to automatically expire old data.
// Cassandra: Auto-delete after 30 days
INSERT INTO sensor_data (...) VALUES (...)
USING TTL 2592000;
// MongoDB: TTL index (expires after 24 hours)
db.logs.createIndex(
{ "createdAt": 1 },
{ expireAfterSeconds: 86400 }
);Different operations need different consistency guarantees. Don't use strong consistency everywhere, it kills performance.
| Use Case | Consistency Level | Reasoning |
|---|---|---|
| Financial transactions | QUORUM/ALL | Money must be accurate |
| Page view counts | ONE | Approximate is fine |
| User profile updates | QUORUM | Balance speed/accuracy |
| Sensor readings (IoT) | ONE | High volume, eventual OK |
NoSQL databases behave differently at scale. What works with 1GB might fail with 1TB.
Load Testing Checklist:
- Test with production-like data volume (10x current size)
- Simulate realistic query patterns and concurrency
- Test node failures, does it recover gracefully?
- Measure performance during compaction/maintenance
- Test with network partitions (chaos engineering)
- Verify backup/restore procedures at scale
Decision Framework: Which Database?
Start with These Questions:
1οΈβ£ Can your data fit on one server (now and in 3 years)?
If YES: Use PostgreSQL or MySQL. Don't overcomplicate.
If NO: Continue to question 2
2οΈβ£ Do you need complex joins and transactions?
If YES: Consider PostgreSQL with sharding (Citus) or CockroachDB
If NO: Continue to question 3
3οΈβ£ What's your primary workload?
Massive writes, time-series: β Cassandra
Flexible documents, rich queries: β MongoDB
Hadoop integration, sparse data: β HBase
4οΈβ£ What's more important: Availability or Consistency?
Availability (AP): β Cassandra
Consistency (CP): β MongoDB or HBase
Quick Reference Guide
Choose Cassandra If:
- Writing millions of events/sec
- Time-series or IoT data
- Need 99.999% availability
- Multi-datacenter required
- Simple query patterns
Choose MongoDB If:
- Building web applications
- Need flexible schemas
- Want rich query language
- Need aggregations
- Fast iteration/prototyping
Choose HBase If:
- Already using Hadoop
- Billions of rows, sparse
- Need strong consistency
- Sequential access patterns
- Historical versioning
Common Pitfalls to Avoid
β Using NoSQL Like SQL
Mistake: Normalizing data, expecting joins to work
Solution: Denormalize, duplicate data across tables designed for specific queries
β Ignoring Partition Key Design
Mistake: Using timestamp as partition key (all writes hit one node)
Solution: Use high-cardinality keys (user_id, device_id) or composite keys
β Over-Using Strong Consistency
Mistake: ALL consistency for every operation (kills throughput)
Solution: Use QUORUM for most, ONE for analytics, ALL only when critical
β Not Planning for Growth
Mistake: No TTL policies, data grows forever
Solution: Implement TTL early, archive old data to object storage
β Poor Monitoring Setup
Mistake: No visibility into cluster health until it's too late
Solution: Set up comprehensive monitoring from day 1 (Prometheus, Grafana)
β Underestimating Operational Complexity
Mistake: Treating NoSQL like a managed service when self-hosting
Solution: Use managed services (AWS, Atlas, Astra) or hire experienced DBAs
Real-World Use Cases
Netflix, Cassandra
Streaming Analytics Platform
Challenge: Track viewing history for 200M+ users globally
Solution: Multi-datacenter Cassandra cluster (2500+ nodes)
Scale: 1 trillion writes/day, 420TB data
Why Cassandra? Masterless architecture = no single point of failure, linear scalability, and fast writes for real-time viewing data.
Adobe, MongoDB
Creative Cloud Platform
Challenge: Store diverse assets (images, videos, metadata)
Solution: MongoDB sharded cluster
Scale: 80TB data, millions of users
Why MongoDB? Flexible schema for varied asset types, rich queries for searching, and fast iteration on features.
Facebook, HBase
Messages Platform
Challenge: Store billions of messages with quick retrieval
Solution: HBase on top of HDFS
Scale: 135+ billion messages/month
Why HBase? Handles sparse data (not all columns set), strong consistency for message ordering, and integrates with Hadoop for analytics.
Uber, Cassandra
Trip Data Storage
Challenge: Store location data from millions of trips daily
Solution: Cassandra across multiple datacenters
Scale: Petabytes of trip/location data
Why Cassandra? Time-series data (GPS points), massive write throughput, and global availability for multi-region operations.
Key Takeaways
- NoSQL is not a silver bullet, use it when you've truly outgrown relational databases
- CAP theorem matters, understand your consistency vs availability trade-offs
- Design for queries first, unlike SQL, you model data around access patterns
- Partition keys are critical, they determine performance and scalability
- Each has sweet spots, Cassandra for writes, MongoDB for flexibility, HBase for Hadoop
- Operational complexity is real, consider managed services unless you have expertise