Skip to main content

Choosing a Data Compression Strategy Without Repeating Your Worst Storage Bloat Mistakes

You know the feeling. You log into your data lake dashboard, and the storage meter is climbing. Not a slow creep—a sprint. Someone loaded a year of raw clickstream logs without thinking about compression. Or worse, they picked a codec that made the files unreadable by downstream tools. You're not alone. I've watched teams burn months of engineering time re-encoding Parquet files because they chose Snappy for everything, then wondered why their analytical queries crawled. The mistake wasn't compression itself. It was treating compression as an afterthought. So let's fix that. This isn't another list of compression ratios and benchmarks you can find on Wikipedia. It's a field guide—drawn from real data pipelines, messy production clusters, and the trade-offs that actually matter when you're choosing a strategy that won't force you to redo everything six months from now.

You know the feeling. You log into your data lake dashboard, and the storage meter is climbing. Not a slow creep—a sprint. Someone loaded a year of raw clickstream logs without thinking about compression. Or worse, they picked a codec that made the files unreadable by downstream tools. You're not alone. I've watched teams burn months of engineering time re-encoding Parquet files because they chose Snappy for everything, then wondered why their analytical queries crawled. The mistake wasn't compression itself. It was treating compression as an afterthought.

So let's fix that. This isn't another list of compression ratios and benchmarks you can find on Wikipedia. It's a field guide—drawn from real data pipelines, messy production clusters, and the trade-offs that actually matter when you're choosing a strategy that won't force you to redo everything six months from now. We'll cover what to compress, when, and—just as important—when to leave your data alone.

Where Compression Decisions Actually Hit Your Workflow

Data lakes: the silent bloat trap

Most teams don't notice compression failure until storage costs spike three months in. By then the data lake is a swamp — Parquet files that should be 200 MB clock in at 2 GB because someone picked Snappy for everything. Snappy is fast. It's also terrible at shrinking repeated text columns. That 'order_status' field with three values? Snappy leaves it nearly raw. Zstandard would cut it 80% without meaningful speed loss. The catch is most people configure data lakes once, at inception, and never re-examine the choice. I've seen a single table of 12 billion rows cost an extra $4,000 a month — just because nobody checked whether the compression codec actually compressed.

Worth flagging: column-level compression is rarely used. Most pipelines apply one codec to the whole file. That means a table mixing short strings, floats, and high-cardinality IDs gets the same treatment across all columns. Wrong order. Floats compress poorly under dictionary schemes; strings compress beautifully. If you shove everything through LZ4, you leave money on the floor for the strings and waste CPU cycles compressing floats that barely shrink. A quick fix: use Zstandard on string-heavy columns, leave floats alone with plain LZ4 — but that requires schema-aware pipeline logic, which most off-the-shelf ETL tools don't expose easily.

'We switched from Snappy to Zstandard on our event logs and cut storage 63% — latency increased 4%. That 4% was invisible to users but the S3 bill dropped $2,100 a month.'

— senior data engineer, e-commerce platform, after a three-hour migration

Streaming pipelines: latency vs. throughput

Real-time systems break differently. Here compression decisions hit latency first — and latency kills throughput. A Kafka topic with gzip compression looks great on disk: tiny messages, low broker storage. But gzip is CPU-bound. When your producer nodes are already pegged at 70% serializing JSON, adding gzip pushes them to 95%. Now messages queue. Consumers back-pressure. Lag grows. The pipeline doesn't crash — it just bleeds timeliness, slowly, until some critical alert arrives thirty seconds late. That's not a storage problem; it's a compression problem disguised as a capacity problem.

What usually breaks first is the trade-off nobody documented. A team picks lz4 for speed during development, then promotes to production. Six months later a partner requires Parquet output with Snappy. Someone adds a conversion step. The conversion is CPU-heavy because lz4 decompression plus Snappy recompression doubles the work. The pipeline slows 40%. Nobody thinks to check: could the partner accept Zstandard? Could we write directly in Snappy from the source? The seam blows out because compression decisions were treated as independent, not cascading. Most teams skip this: map your compression choices end-to-end before you wire anything in production.

Archival storage: cold data, hot bills

Archival is where bad compression really stings — because you're paying for data you almost never touch. A 500 TB S3 Glacier bucket with suboptimal codec might cost $2,000 extra per month. That's pure waste: no query benefit, no latency advantage, just dead storage bloat. I once consulted with a fintech firm that archived raw trade logs in plain-text JSON. No compression at all. The architect's reasoning: 'We rarely read it, so why bother?' The answer: because 50 TB of JSON at $0.023/GB/month is $1,150 a month — versus 5 TB of Zstandard-compressed Parquet at $115. Same data. Same retention. One tenth the cost.

The tricky bit is you can't always re-archive retroactively. Some cloud providers charge egress fees to pull cold data, recompress it, and re-upload. You might spend $3,000 once to fix a mistake that bleeds $1,000 a month — worth it after four months, painful before that. The better move: bake compression into the archival path from day one. Use Zstandard level 19 for cold data — it's slow to write, but you write it once. Reads are infrequent, so the speed loss is irrelevant. That's one concrete decision you can make tomorrow morning: check your archival bucket's average object size. If objects are under 1 MB and uncompressed, you're burning money. Fix the pipeline, not the archive. That hurts less than the monthly invoice.

Foundations People Mix Up

Compressed vs. Uncompressed File Formats — The Obvious Trap

People treat compression as a toggle. Flip it on, files shrink. Flip it off, they grow. That mental model burns more engineering hours than any cluster outage I've debugged. The real split isn't 'compressed versus raw' — it's 'splittable compressed versus everything else.' Take a 2 GB CSV poured into gzip. Looks great on disk. Then you try to run a Spark job on it, and suddenly only one executor can read it at a time. Gzip is not splittable. Your twenty-node cluster idles while a single core decompresses the entire file. That's not a storage win; that's a bottleneck you paid for. Hadoop's SequenceFile and Parquet, by contrast, compress internally while keeping blocks independent — you can read them in parallel without decompressing the whole dataset. The trade-off? Slightly larger files than a monolithic gzip, but your job finishes in minutes instead of hours.

Worth flagging—uncompressed plain text isn't always the enemy. I've seen teams jump to Snappy-compressed Parquet for everything, then wonder why simple ad-hoc queries via Hive crawl. Sometimes a flat CSV, uncompressed, sitting on a fast SSD array, outperforms the 'optimized' binary format for one-off reads. The trick is knowing the read pattern before you pick the format. Not after.

'We compressed everything because disk was expensive. Then our batch jobs stopped finishing overnight. Disk wasn't the problem anymore — data access was.'

— Site reliability engineer, post-mortem on a failed migration to full gzip

Flag this for data: shortcuts cost a day.

Flag this for data: shortcuts cost a day.

Splitability — Why MapReduce Chokes Without It

Splitability is the concept most teams skip until it bites them. A file is splittable if the processing framework can divide it into chunks and assign each chunk to a different mapper. That's how MapReduce scales. Without splitability, your parallelism collapses to one. The catch? Compression algorithms like gzip and bzip2 produce output where each byte depends on the prior byte — you can't find the natural boundaries. LZO and Snappy, however, are block-level compressors. Each block is self-contained. That means a 10 GB LZO-compressed CSV splits into, say, eighty map tasks that run concurrently. Same dataset, same cluster, but your job finishes before coffee gets cold.

What usually breaks first is the assumption that 'compressed' automatically means 'fast.' It doesn't. I fixed a pipeline once where the team had switched from LZO to bzip2 for better compression ratios. Disk usage dropped 40%. Job runtime increased 300%. The bzip2 decompression was CPU-bound and not splittable in the way they'd configured it. The rollback took two weeks. Don't optimize for storage cost alone — optimize for throughput per dollar per clock cycle.

CPU vs. I/O — The Trade-off That Keeps Shifting

Most teams frame this as a simple equation: compress more to save I/O, compress less to save CPU. Wrong framing. The real variable is your cluster's bottleneck. On spinning disks with moderate network bandwidth, heavier compression (bzip2, high-level gzip) can be a net win — you trade CPU cycles for fewer disk seeks. On NVMe SSDs with 40 GbE networking, the CPU cost of decompression often exceeds the I/O savings. That's when Snappy or LZ4 becomes the sweet spot. I have seen Spark shuffles double in duration simply because the default compression was set to gzip level 9 instead of Snappy. The data moved fewer bytes but spent more time decompressing than waiting on the network. That hurts.

One litmus test: if your CPU utilization is pinned at 95%+ during a read-heavy job and your disk queue length is near zero, your compression is too aggressive. Flip to something lighter. If your CPUs are idle and your disks are thrashing, you can afford more compression. Simple heuristic — but I've watched teams ignore it for quarters, chasing a 'standard' that didn't match their hardware. Tomorrow morning, check your Spark spark.io.compression.codec and your MapReduce mapreduce.map.output.compress.codec. Change one of them to Snappy if it isn't already. Run the same job, compare runtime. That five-minute test will teach you more than any benchmark blog post.

Patterns That Usually Survive First Contact

Snappy for speed, Zstd for ratio

Most teams skip past the boring part—the actual latency profile of their pipeline. I have seen a real-time feed collapse because someone picked gzip for a Kafka topic. Wrong order. Snappy trades 10–15% compression ratio for sub-microsecond decompression; it's the right call when your downstream consumer is a dashboard that refreshes every second. Zstd, by contrast, rewards you with 2–3× better density but burns 200–400 nanoseconds per byte on decompression. That sounds fine until your batch job processes 500 million rows nightly and suddenly the wall clock jumps from two hours to seven. The catch is—you have to know which side of the clock your team cares about. Speed-first streaming? Snappy. Cold storage or archival? Zstd at level 3, not the default 19.

Columnar formats: Parquet and ORC

Row-based formats (CSV, Avro) feel natural because humans think in rows. Machines don't. Parquet and ORC store data column-by-column, which means a query asking for three fields out of thirty can skip 90% of the I/O. We fixed a reporting pipeline that was taking 45 minutes by switching from CSV.gz to Parquet with Snappy compression—the same query ran in under four minutes. No schema change, no hardware bump. But columnar formats punish you if your workload is heavy on single-row inserts or frequent updates. Every new record forces a rewrite of the row group. That hurts. The pragmatic pattern: use Parquet for analytics-heavy tables that get written once per day, and keep Avro or JSON for event streams that need append-only performance.

Indexing strategies that preserve query performance

Compression and indexing often fight each other. A dictionary-encoded column compresses beautifully—until you try to run a range scan on it. The decompression cost per row group can erase the I/O savings. I have watched engineers slap a B-tree index on a Zstd-compressed Parquet table and wonder why their filter still took ten seconds. The answer: the index pointed to compressed pages, and each page hit required a full decompression pass. Sparse indexing works better—store min/max statistics per row group, skip entire groups that don't match the filter. Most columnar formats do this automatically, but only if you sort the data before writing. That's the step people skip. Sort once, partition by date, then compress. The order matters more than the algorithm.

'We switched from gzip to Zstd and lost query performance—turns out our index was pointing at compressed pages, not decompressed ones.'

— Data engineer, mid-size SaaS analytics team, after a three-day rollback

Avoid the same trap: measure your index's page-access pattern under real compression, not synthetic benchmarks. What looks good in a lab often seizes up under production concurrency. The next morning, pick one table that hurts the most, sort it by your most-common filter column, write it as Parquet with Snappy, and compare the query time. That single change usually survives first contact. If it doesn't, you've learned something about your access pattern that no blog post can predict.

Anti-Patterns That Force a Rollback

Over-compressing hot data

You snapper a column with Gzip level 9 and watch the file size drop. Feels good. That feeling lasts about three hours—until the dashboard queries that column eight hundred times per minute. Every read now decompresses a dense block of integers that nobody actually needed compressed. The CPU pins. The query latency doubles. One team I worked with rolled back six months of Parquet tables in a single afternoon because their "storage win" became a 4x compute penalty on their hottest fact table. The fix wasn't smarter compression—it was no compression on the frequently filtered columns and a lighter codec (Snappy or LZ4) on the rest. Compression is a tax on read speed. Pay it only on cold data, or data you write once and rarely touch.

Ignoring row group sizes in Parquet

Parquet isn't a magic box. It's a row-group machine. If you cram thirty million rows into a single row group, compression works great—but your Spark executor can't split that work across cores. You lose parallelism. The opposite mistake: tiny row groups, say 64K rows each, where the compression dictionary barely fills before the group ends. The storage bloat comes back, and the metadata overhead swamps your driver memory. The sweet spot? Usually 512K to 1M rows per group, but it depends on your column cardinality. I once saw a 300 GB table shrink to 90 GB purely by moving from 128K row groups to 768K—then watch query times drop because the files finally matched the cluster's core count.

We compressed everything to bone-dry, then wondered why our dashboards took a coffee break every morning.

— Data engineer, post-mortem on a $12k over-provisioned cluster

Field note: data plans crack at handoff.

Field note: data plans crack at handoff.

Picking a codec that kills parallelism

Zstandard is fast. Gzip is small. But try using Zstd with a high compression level on a streaming pipeline—you'll block the next stage while waiting for a single partition to finish. The real anti-pattern: choosing a codec without testing it against your write pattern. Batch writes? Snappy or LZ4. Cold archive? Zstd level 3 or Gzip. Streaming? Stick with Snappy—it's not the best at anything, but it never surprises you. The worst rollback I've witnessed came from a team that switched all their Kafka topics to Zstd level 19. Compaction took 8x longer, consumer lag exploded, and they reverted within 48 hours. The lesson: compression level isn't a slider you max out for fun—it's a lever that trades CPU for storage, and your data's lifecycle decides which side wins.

What usually breaks first is the assumption that "more compression = better." It isn't. Better compression means your system survives a rebalance without OOMing, or your ETL finishes before the morning standup. That's the bar. Everything else is a rollback waiting to happen.

The Long Tail: Maintenance and Drift

Data Evolution and Codec Compatibility

The compression you chose last year was perfect for flat JSON blobs with three string fields. Now your schema nests arrays, timestamps have shifted from ISO strings to Unix epochs, and someone added a 4KB binary fingerprint column. That codec you loved? It's suddenly producing ratios that look like a joke — or worse, it's silently inflating storage because the library treats your new column types as incompressible noise. I have watched teams burn two sprints re-encoding 12 TB after a schema migration exposed a codec's hidden ceiling. What usually breaks first is the mismatch between what the compression algorithm expects (predictable, repetitive byte patterns) and what your data actually delivers after six months of organic schema drift.

The catch is that most compression libraries don't warn you. They just keep chewing cycles and spitting out bloated blocks. You don't get an alert that says 'hey, your Parquet page size collapsed because your new nullable UUID column is random noise to my dictionary encoder.' Instead, your nightly batch job starts timing out, or your query engine starts spilling to disk. We fixed this once by pinning a codec version to each table's metadata annotation — a pragmatic brute-force hack that forced schema-review triggers before any compression change. Not elegant, but it caught the seam before it blew out.

Re-compression Overhead Over Time

Ratcheting up compression on older partitions feels like a safe bet. Until you realize that re-compressing 40 TB of cold data runs hot — it pegs CPU, thrashes the I/O pipeline, and blocks reads on partitions your analysts need for month-end reporting. That's the hidden tax: every pass of re-encoding adds latency debt that compounds as clusters scale. The worst anti-pattern is running a blanket background job that re-compresses everything nightly. Wrong order. You want to touch only partitions where the compression ratio degraded below a threshold, and you want to schedule that during a maintenance window no wider than two hours. Most teams skip this granularity — they treat re-compression as a one-time migration, then discover six months later that the drift has returned.

One concrete anecdote: a team I consulted had a pipeline that appended daily logs, compressed with Zstandard at level 3. The first month looked great — 4:1 ratio. By month four, the ratio had slid to 2.3:1 because log verbosity increased and field order changed. Instead of re-compressing everything, we wrote a probe that sampled 100 blocks per partition and only flagged partitions below a 3:1 ratio. That reduced the weekly re-compression footprint by 80% and kept CPU overhead flat. The trick was accepting that drift happens — you just build a cheap sensor, not a full rebuild.

Hidden CPU Costs in Production

Compression doesn't sit still when your tooling updates. A minor Parquet library bump from version 1.12 to 1.13 can change default block sizes, shuffle dictionary encoding thresholds, or deprecate a codec variant your pipeline depends on. You don't notice until query latency spikes by 40% because the new reader is decompressing with a different strategy — one that's 30% slower for your particular data shape. That sounds fine until you multiply it across 500 concurrent queries. Worth flagging — we once saw a 10x increase in decompression CPU after a Spark upgrade switched from Gzip to Zstandard defaults silently. The fix wasn't rolling back; it was explicitly setting the codec in every write path, including the config files nobody remembers to check.

Blockquote optional, but if I include one, it's this:

Every compression choice you make today is a maintenance contract you sign with your future operations team.

— muttered by a senior data engineer after a 3 AM incident, 2023

The real strategic move is to build a compression decision log — a living document that records why you chose LZ4 over Snappy for that stream, what schema shape it expects, and which cluster version it was tested against. Then, every quarter, you run a light audit: re-measure ratios on a sample of partitions, check CPU usage for decompression across your top 20 queries, and confirm that tooling upgrades haven't silently shifted defaults. That's the long tail — not a firefight, but a persistent, low-grade attention tax. Ignore it, and your storage bloat repeats. Pay it, and you get predictable costs and a team that sleeps through the night.

When Compression Hurts More Than Helps

Real-time analytics with sub-second SLAs

Compression adds latency. That sounds obvious until you're staring at a dashboard that refreshes every 800 milliseconds and your Parquet snappy pipeline just added a 200-millisecond decompression tax on every query. I have seen teams bake columnar compression into their ingestion layer, only to discover that their real-time Kafka consumer now misses windowed aggregations because the decompression step backs up under load. The trade-off is brutal: you save 40% disk space but your p99 query latency jumps from 600ms to 1.2s. Worth flagging—if your SLA demands sub-second responses and your data arrives in small batches (under 1MB per read), skip compression entirely or use a lightweight scheme like LZ4 with no dictionary. The catch is that most storage engines default to maximum compression ratios. Check your config. Not your disk.

Append-only logs with sequential reads

Logs are the classic case where compression makes things worse. Why? Because you almost always read them sequentially from tail to head, and modern CPUs can scan raw text faster than they can decompress gzipped blocks. We fixed this by running a side-by-side benchmark on a 200GB syslog archive: uncompressed reads at 450MB/s versus compressed reads at 180MB/s after decompression overhead. That hurts. The disk savings look great—70% smaller—but your incident response team loses minutes every time they tail a file.

'We compressed everything because the storage team said so. Then debugging a production outage took three times longer.'

— Senior SRE, after a postmortem they'd rather forget

Odd bit about data: the dull step fails first.

Odd bit about data: the dull step fails first.

Pattern to follow: compress logs for archival (older than 90 days), leave the hot partition raw. Your grep commands will thank you.

Data already compressed by source systems

Compressing already-compressed data. A mistake so common it has a name: double compression. When you ingest JPEG images, MP4 video, or gzipped JSON blobs, applying another compression layer yields negligible space savings—often below 3%—while burning CPU cycles on both write and read paths. Most teams skip this check because they apply compression policies uniformly across all columns. Don't. Profile your binary columns first. If the entropy is already high, you're just spinning fans. The anti-pattern shows up worst in data lakes: Spark jobs that write compressed Parquet files containing columns that were already snappy-compressed upstream. Result? Output sizes barely shrink, job runtime increases 15-25%, and nobody notices until the cluster bill arrives. We stopped this by adding a simple entropy check before compression: if the column's Shannon entropy exceeds 7.5 bits per byte, skip the codec. Not fancy. Works.

Open Questions and FAQ

Adaptive compression: myth or reality?

Every team I've worked with eventually asks the same question: can the system just figure out the right compression on its own? The short answer is no — not yet, not reliably. Adaptive compression algorithms exist, sure, but they tend to optimize for the last five minutes of data, not the next five years. You'll see them switch from Snappy to Zstd mid-stream because a burst of text-heavy records shows up, then bloat the whole partition when the next batch is mostly floats. The trade-off is brutal: you gain maybe 8–12% space in mixed workloads, but you lose deterministic behavior in query planning. That said, one pattern does work: run a small sample job before the main write pipeline — not adaptive per-record, but adaptive per-batch. We fixed a client's nightly load by pre-sampling 1,000 rows from each shard and picking the codec that minimized stored size for that specific batch. It added 40 seconds to a four-hour job. Worth it.

"Adaptive compression is like a self-driving car that only works on the highway — great until you hit a parking garage."

— overheard at a data engineering meetup, describing why they rolled back after three weeks

Hybrid strategies for mixed workloads

Most people assume you pick one codec per table or per column. Wrong move. The real answer is messier — you segment by data shape, not by storage layer. Text-heavy columns? Zstd at level 3 or 6, never higher. Integer sequences with narrow ranges? Delta encoding before you even think about compression. Timestamps sorted by ingestion order? Run-length encoding wins every time. I have seen a single Parquet file where column A needed Gzip level 1 and column B needed uncompressed — the file was 30% smaller than the uniform-Zstd alternative. The catch is complexity: your schema logic now embeds compression rules, which means schema evolution gets tangled. When you add a column, you also add a compression decision. That hurts. What usually breaks first is the orchestration layer — Airflow or Dagster doesn't know a codec changed, so the downstream reader chokes on a format it wasn't expecting. One pitfall: don't let your data pipeline auto-detect the codec from the file header and silently switch. That creates drift between what you think is compressed and what actually lands on disk.

What to do when your data is already compressed

You inherited a petabyte of gzipped JSON. Now what? Don't decompress and recompress — that's a day of compute for 5% space gain, tops. Instead, ask a harder question: is the data accessed cold or warm? Cold data that stays compressed and rarely read should stay as-is. Warm data where you filter heavily? Partial decompression at query time, using columnar readers that seek inside gzip blocks. It's ugly but it works. The nasty surprise: if your data came from a source that used gzip --fast with default window sizes, you lose splitability — Hadoop and Spark can't parallelize reads across block boundaries. I've seen teams spend two weeks building custom splitters for what should have been a one-hour config change. Your next action: check the compression block size on every ingested file. If it's larger than 64 KB, stop the pipeline and renegotiate with the producer. That single number determines whether your query latency is 200 milliseconds or 20 seconds. Not yet convinced? Run a quick test on one month of data: measure scan time with the current codec, then with a columnar-aware alternative. The difference will tell you whether to push back or pay down the technical debt gradually—never all at once.

Where to Start Tomorrow Morning

Benchmark your own dataset, not synthetic

Grab a representative slice of your actual production data—think 24 to 48 hours of real writes—and run it through your top three compression candidates. Synthetic benchmarks are a trap; they compress beautifully because they lack the messy nulls, repeated UUIDs, and skewed distributions your real workload carries. I once watched a team celebrate a 12:1 ratio on a canned test set only to see that ratio collapse to 3:1 on Monday morning. The catch is that a single test pass isn't enough. Run it at least three times, at different hours, when your pipeline is under load. You'll spot variance that a clean lab environment simply masks.

That sounds fine until you realize your dataset isn't static. It drifts—new fields appear, old ones fill with garbage, cardinalities shift. So benchmark again every quarter. Really. The compression ratio you picked in January might be a liability by April.

Test splitability with your processing engine

Compression that prevents your downstream engine from splitting files is a non-starter—yet most teams skip this check. Fire up your exact Spark, Flink, or Presto configuration and try to read a single column from a compressed file. If the engine decompresses the whole block just to grab one field, you're burning I/O and memory for data you will never touch. Wrong order. The splitability test should happen before you commit to a codec, not after your nightly job starts timing out.

What usually breaks first is the interaction between block compression and your partition pruning logic. A clever gzip scheme on a Parquet file looks great on disk, but if your query engine can't skip irrelevant row groups because the entire block must inflate first, your scan costs spike. Test this with a query that touches 5% of your data. If the engine reads 95% anyway—you've got a problem.

One team I know rolled back a LZ4-based strategy inside a month. They'd benchmarked compression ratios but never checked that their streaming engine needed to resplit compressed chunks mid-pipeline. The seam blew out under memory pressure. Not a fun rollback meeting.

Set a compression cost budget

Compression is never free—it's a trade-off between storage dollars and compute cycles. Most people track only the saving, not the cost to achieve it. That hurts. Define a simple metric: cost per saved gigabyte, measured in CPU seconds. If your compression ratio improves by 5% but your processing time jumps 40%, you may be losing money on every write.

The tricky bit is that costs shift under load. A codec that runs fine at 10MB/s might crater your ingestion latency at 100MB/s. So budget for peak, not average. Ask yourself: What's the maximum CPU tax I'm willing to pay per terabyte written? Set that as your ceiling. Then when someone pitches a new compression scheme, you can reject it on budget grounds before wasting a week on benchmarks. "That would bust our cost budget" is cleaner than "we tried it and it wrecked our SLA."

'Every compression win is a bet against future access patterns. Make sure you're betting with real data, not hope.'

— engineer who learned this the hard way, after a 200TB rollback

Share this article:

Comments (0)

No comments yet. Be the first to comment!