Operational vs. Analytical Systems: Why the Oldest Divide in Data Exists, What Physics Enforces It, and the Honest Truth About Hybrid Systems
Cross-posted. This article's canonical home is iceberglakehouse.com.
Operational vs. Analytical Systems: Why the Oldest Divide in Data Exists, What Physics Enforces It, and the Honest Truth About Hybrid Systems
By Alex Merced, Head of Developer Relations at Dremio
Every data architecture ever drawn contains the same fault line, so old and so universal that most engineers stop seeing it: on one side, the systems that run the business, and on the other, the systems that understand it. The database behind your checkout page and the warehouse behind your dashboards. OLTP and OLAP, in the acronyms the industry has used since the 1990s.
The divide is expensive. It means two systems, two copies of the truth, pipelines between them, freshness lag, governance gaps, and a permanent tax of reconciliation. So for thirty years, vendors have promised to erase it, one system for everything, and for thirty years the divide has survived every promise. Then, in the past eighteen months, the campaign escalated dramatically: Snowflake acquired a PostgreSQL company, Databricks acquired one too and launched Lakebase, then declared a whole new architecture around it, cloud providers shipped zero-ETL integrations, and the term HTAP, hybrid transactional and analytical processing, returned from its rest wearing new names.
So this article is the full treatment the moment deserves. What operational and analytical workloads actually are, described honestly. Why their architectures diverge, not by convention but by physics, row versus column, B-tree versus immutable file, latency versus throughput, tracing all the way down to the storage tiers underneath. What happens when you ignore the divide, the two classic anti-patterns that still cause half the incidents I hear about. The full history of hybrid attempts, what worked, what quietly did not, and why the industry's smartest players just changed strategies. And a clear-eyed framework for the architecture decisions this leaves you with, because the divide is not going away, but the cost of living with it has collapsed, and that changes almost everything.
The Two Workloads, Described Honestly
Strip the acronyms and describe what each side actually does all day, because every architectural consequence follows from the workload shapes.
An operational system, OLTP, online transaction processing, is the system of record for the business's current state, and its workload is a torrent of tiny, urgent, independent operations. Look up this customer's account. Insert this order. Decrement this inventory count. Update this session. Each operation touches a handful of rows, must complete in milliseconds because a human or a service is waiting mid-action, must be correct under fierce concurrency, thousands of these operations interleaving per second, and must be durable the instant it commits, because it is the truth: the order exists, the payment happened, the seat is taken. The defining acronym is ACID, atomicity, consistency, isolation, durability, and the defining question is always about now: what is this entity's current state?
An analytical system, OLAP, online analytical processing, asks the opposite kind of question: not what is this row's state, but what does the whole history say? Revenue by region by month. Conversion trends across two years of events. The cohort behavior behind a churn model. Its workload is a small number of enormous operations: queries that scan millions or billions of rows, touch a few columns of many, aggregate massively, and return summaries. Latency budgets stretch from seconds to minutes, individual row-level freshness matters less than completeness and consistency of the whole, writes arrive in bulk, batches and streams, rather than as urgent singletons, and the system's value scales with how much history it can hold and how fast it can scan it.
Put the two profiles side by side and notice they conflict on essentially every axis: many tiny operations versus few huge ones, milliseconds versus seconds, rows versus columns of interest, current state versus deep history, write-hot versus read-scan-hot, human-waiting versus analyst-waiting. These are not two customer segments for one product. They are close to opposite specifications, and that is before the physics gets involved.
The Physics of the Divide: Why One Architecture Cannot Serve Both Well
Here is the heart of the article, because the divide's persistence is not an industry failure or a vendor conspiracy. It is enforced by a chain of physical trade-offs, each of which forces a fork, and every fork gets taken in opposite directions by the two workloads.
Fork one: how rows are laid out. Store a record's fields together, row orientation, and fetching or updating one entity is one localized operation, exactly what OLTP does a thousand times a second. Store each column's values together, columnar orientation, and scanning one attribute across a billion rows reads only that attribute, compressed superbly because similar values sit adjacent, exactly what OLAP does all day, the property that all of modern columnar compression and encoding is built on. But each layout is pessimal for the other side's work: assembling one full row from a columnar store means gathering fragments from everywhere, and scanning one column of a row store means reading every byte of every record to keep three percent of it. The layout fork alone nearly settles the argument.
Fork two: how data is found and changed. OLTP's tool is the index, above all the B-tree: a structure updated in place with every write, purchased with write-time work and maintained forever, so that any single row is a few hops away. OLAP's tool is statistics and pruning over large immutable files: no per-row indexes to maintain, writes land as bulk appends, and queries skip data wholesale using min-max metadata. In-place mutation versus immutability-plus-rewrite is as deep as forks get: the entire lakehouse machinery, snapshots, deletion vectors, compaction, exists because analytical storage chose immutability, and the entire discipline of database internals, buffer pools, write-ahead logs, page management, exists because operational storage chose mutation.
Fork three: how concurrency is controlled. Thousands of interleaved writers touching overlapping rows demand fine-grained machinery: row locks, multiversion concurrency control, transaction isolation enforced at the row and page level, all costing overhead per operation that OLTP gladly pays for correctness. Analytical readers want a consistent snapshot of everything and no interference, which immutable snapshots provide almost for free, and analytical writers are few and bulky, needing only coarse coordination, the optimistic snapshot commits of the table formats. Neither concurrency machine handles the other workload gracefully: row-lock machinery melts under scan pressure, and snapshot-commit machinery makes per-row updates absurd.
Fork four: the storage tier itself. Everything above lands on the divide my block-versus-object deep dive mapped: OLTP's point operations demand the sub-millisecond, mutate-in-place contract of block storage and local NVMe, while OLAP's scans thrive on object storage's infinite, cheap, parallel throughput and tolerate its latency because formats and engines amortize it away. The workloads do not just want different software. They want different physics under it, and cloud economics reward giving each exactly what it wants.
And fork five: the modeling layer humans build on top. Operational schemas normalize, splitting facts across many tables to make each update touch one place, keeping writes cheap and consistent. Analytical schemas denormalize, flattening into wide tables and star shapes to make reads cheap, precomputing the joins that scans would otherwise repeat forever. Same information, opposite shapes, and the transformation between them is real intellectual work, which is worth flagging now because every "no more pipelines" pitch quietly hopes you forget it.
Five forks, ten opposite choices, one conclusion: a single system can sit at either end and excel, or sit in the middle and compromise everywhere. That is the theorem the last thirty years kept testing, and the test results are the rest of this article.
The Life of Two Queries: Watching the Physics Work
Abstract forks land best traced through real operations, so follow two queries through their proper homes, and then, briefly, through the wrong ones.
Query one: SELECT * FROM accounts WHERE account_id = 88231, plus an update to its balance, the operational classic, running on Postgres. The engine hashes into its buffer pool, likely finds the B-tree's upper levels already in memory, descends three or four nodes to the leaf holding account 88231's row pointer, and fetches one 8-kilobyte page from sub-millisecond block storage on the rare miss. The row's fields sit together on that page, row orientation earning its keep, so the read is done in microseconds. The update writes the new balance to the page in memory, appends a record to the write-ahead log, whose sequential flush is the durability guarantee, takes a row-level lock for exactly as long as the transaction needs, and commits. Total work: a few pages touched, one log append, milliseconds end to end, repeatable fifty thousand times a second across the fleet. Every design choice in the stack, the tree, the pool, the log, the locks, the block storage underneath, exists to make this specific dance cheap.
Query two: revenue by region for the trailing quarter across two billion order rows, the analytical classic, running on a lakehouse engine over Iceberg. No tree descent happens and no row is ever sought: the engine reads cached table metadata, prunes at the snapshot level using partition values and column statistics, and eliminates, say, 96 percent of the data files without touching them. For the survivors, Parquet footers locate exactly three columns' byte ranges, order date, region, amount, and the engine launches hundreds of parallel ranged reads against object storage, latencies overlapped into throughput, pages decompressed into Arrow batches and aggregated by vectorized kernels at billions of values per second per core. No locks, because the snapshot is immutable. No index maintenance ever happened, because statistics did the finding wholesale. Seconds end to end over terabytes, and every design choice, columnar layout, immutable files, statistics, object storage's parallel cheapness, exists for this dance instead.
Now swap them, briefly, and the anti-patterns section becomes mechanical rather than moralistic. The analytical query on Postgres has no columns to isolate and no statistics to prune with: it walks every page of a two-billion-row table through a buffer pool sized for point lookups, evicting the working set that queries like account 88231 depend on, which is precisely why the checkout stalls when the report runs. The point update on the lakehouse finds no B-tree waiting: it triggers the full merge-on-read apparatus, a new file or deletion-vector write, a metadata commit, a snapshot, for one row, and at application frequencies that apparatus becomes a small-file blizzard and constant metadata churn. Same queries, wrong physics, and now the incident reports explain themselves.
Crossing the Streams: The Two Anti-Patterns
Before the hybrids, the failure modes, because they are how most teams learn the physics personally, and both remain everyday incidents in 2026.
Anti-pattern one: analytics on the operational database. It always starts innocently: the data is right there, one analyst gets read access, one dashboard gets pointed at production. Then the group-by arrives, a scan-shaped query on a row store with row locks and a buffer pool sized for point lookups, and it evicts the working set, saturates I/O, and stalls the tiny urgent operations that pay the company's bills. The signature is unmistakable: checkout latency spiking at 9 a.m. when the reports run, P99 graphs that follow the analysts' calendar. The correct responses have been standard for decades, read replicas as first aid, real analytical systems as the cure, and federated access with guardrails, workload limits, acceleration, for the cases where querying the source is genuinely the right call. The incidents persist anyway, because the data really is right there, and physics does not care how convenient it looks.
Anti-pattern two: operational patterns on the analytical system. The mirror image: treating a columnar warehouse or lakehouse table like an application database, per-row updates at high frequency, point lookups in tight loops, dozens of tiny commits per second. Every operation technically works, and each one triggers heavy machinery, rewrites or delete records, new snapshots, metadata churn, small files, and the system degrades into a compaction treadmill serving latencies no application can live on. The tell is an "operational dashboard" requirement that quietly became an application, or an agent loop doing row-at-a-time writes against Iceberg. The fix is naming the workload honestly and giving it an operational home, which, as we will see, has never been easier to place adjacent to the analytical estate.
Both anti-patterns are the same mistake in opposite directions, workload denial, and the reason this article spends so long on the physics is that teams who understand the forks stop committing it.
The Classical Answer and Its Costs: Two Systems Plus Pipelines
The orthodox architecture, dominant for thirty years, accepts the divide fully: an operational tier of purpose-built databases, an analytical tier of warehouse or lakehouse, and a pipeline layer, ETL, later ELT, later streaming CDC, moving and reshaping data from the first to the second.
Its virtues are exactly the physics: each tier optimized without compromise, workloads isolated so the analyst can never hurt the checkout, and each side free to evolve, which is how the analytical side got to the open lakehouse era. Its costs are the ones every practitioner recites from memory: two copies and everything copies imply, storage, drift, reconciliation, freshness lag measured historically in hours or days, pipelines as a permanent engineering estate with their own failures and their own team, governance split across systems with different permission models, and the modeling gap, normalized to denormalized, as recurring human work. For decades the summary judgment held: the costs were high, and paying them was still cheaper than fighting the physics.
What changed recently is not the physics. It is the price list, and two developments repriced it: change data capture matured from fragile batch exports into streaming infrastructure that lands operational changes in analytical systems in seconds, and the lakehouse gave the analytical side an open, governed, multi-engine destination worth landing in. Hold that repricing, because it explains everything the vendors did next.
HTAP: The Dream, the Designs, and the Verdict
The perennial alternative has a name and a history worth knowing precisely, because its arc just completed a chapter.
HTAP, hybrid transactional and analytical processing, names the dream directly: one system, both workloads, no pipeline, no copies, no lag. The serious designs all confronted fork one the same way, since row-versus-column cannot be finessed: keep the data in both layouts and hide the duplication inside the engine. TiDB pairs its row-oriented transactional storage with columnar replicas in TiFlash, queries routed to whichever side fits. SingleStore blends row and column structures within one engine. Oracle and SQL Server bolted columnar stores onto their row engines a decade ago. Google's AlloyDB keeps a columnar cache of Postgres data in memory, bounded by RAM. Snowflake approached from the analytical side with Unistore's hybrid tables, row storage grafted onto a columnar platform. Every one of these is real engineering, and several are genuinely good products.
And yet the market verdict, visible in what the biggest players just did with their money, is that HTAP as one-engine-for-everything did not conquer. The industry's own commentary now says the quiet part plainly: the original HTAP framing has been rebranded, and the vendors who most needed it to work went shopping instead. Snowflake did not double down on Unistore, it acquired Crunchy Data to offer genuine PostgreSQL. Databricks did not extend Spark into transactions, it acquired Neon's serverless Postgres and Mooncake's integration technology. The two flagship analytical platforms both concluded that extending one engine across the divide delivers less than composing two purpose-built engines well, which is about as decisive as industry verdicts get.
The reasons compose everything above. The physics taxes the middle: dual-layout engines pay write amplification to maintain both shapes, and each side of the hybrid tends to trail the purpose-built competition on its home workload, a gap buyers eventually price. The ceilings are real, an in-memory columnar cache is capped by memory, a transactional graft onto an analytical platform inherits its parent's assumptions. Isolation, the anti-pattern lesson, is compromised by construction when both workloads share an engine. And the trust problem is commercial rather than technical: betting both your application tier and your analytical tier on one vendor's one engine is a concentration few architects will sign, especially in the decade the industry has spent escaping exactly that concentration through open formats. HTAP survives, honorably, in its niche: moderate-scale estates that value one system over two ceilings. As the industry's central answer, it has been retired by its own former champions.
The New Synthesis: Composed Systems on a Shared, Open Substrate
What replaced the dream is more interesting than the dream, and it is the part of this article that will date fastest, so let me report it precisely as of mid-2026.
The pattern has three moves, all visible across the industry at once. Move one: keep both engines, purpose-built, and stop pretending otherwise. Postgres, overwhelmingly, has become the operational engine of choice in these architectures, which is its own remarkable story, the thirty-year-old open source database as the agreed operational standard, chosen precisely for the same reasons the industry embraced open table formats: no lock-in at the layer everything depends on.
Move two: collapse the pipeline into the platform. Zero-ETL is the honest new name for it, managed, continuous, invisible replication from the operational engine into the analytical substrate, and the implementations span the market: cloud-native integrations flowing operational databases into warehouses and, tellingly, into Iceberg tables for the lakehouse and ML side, CDC platforms delivering single-digit-second freshness as a product rather than a project, with mature CDC and streaming machinery underneath all of it. Read zero-ETL clearly: it is the two-system architecture with the pipeline tax paid by the vendor, an HTAP experience with visible, honest seams, and its trade-offs are the classic managed trade-offs, convenience against lock-in, since these integrations bind you to their specific pairs of endpoints.
Move three, the frontier: shrink the two copies toward one by putting both engines on the same open storage. This is the Lakebase-and-LTAP development, and it deserves careful description with vendor claims handled skeptically. Databricks' Lakebase runs serverless Postgres whose storage architecture separates compute from an object-storage source of truth, write-ahead logs replicated by dedicated services, pages served from the same substrate the lakehouse lives on, with branching and vector search as native features aimed squarely at agent workloads. The subsequent LTAP announcement pushes further: transactional and analytical processing over a single governed copy in open formats under one catalog. The direction is genuinely significant, it is the lakehouse thesis, one open copy, many engines, extended to the operational engine at last, and anyone who has watched a platform launch should recognize both the appeal and the correct posture toward launch-season claims of "no performance trade-offs": the five forks of physics did not repeal themselves in a press release. What changed is where the trade-offs live, pushed down into shared-storage engineering and caching tiers rather than eliminated, and the honest evaluation, as always, is your workloads, measured, once the marketing dust settles.
The open-ecosystem version of the same synthesis is assembling in public, and it is where my own convictions sit: Postgres extensions that read and write Iceberg directly, bridging the operational engine to the open analytical substrate without a proprietary platform in between, Iceberg itself gaining streaming-friendly commit machinery through its v4 design work, catalogs like Polaris governing both sides' metadata, and query federation covering the operational-freshness queries that no replication lag can serve. Composed systems, open substrate, governed seams: the divide managed rather than denied, with every component replaceable.
The Triangle You Cannot Escape
Compress the whole history into the constraint that survives it, because it is the tool you will actually use in design reviews.
Every architecture on this map is choosing among three goods: workload isolation, so each side performs and neither can hurt the other, data freshness across the divide, so analytics sees operational truth quickly, and copy economy, so you store, govern, and reconcile as few copies as possible. The classical two-system stack maximized isolation, sacrificed freshness, and paid for two copies. HTAP maximized copy economy and freshness and sacrificed isolation, which is the sacrifice buyers refused. Zero-ETL keeps isolation, buys freshness down to seconds, and openly pays the two-copy bill with vendor-managed plumbing. The shared-substrate frontier keeps isolation at the compute layer, aims freshness at near-zero, and attacks the copy bill at storage, paying instead in engineering novelty and, for now, platform coupling.
No corner of the triangle is free, and the mature question is never "which architecture wins" but "which good does this workload value least," because that is the one you trade. It is the same style of reasoning that governs streaming freshness floors and storage latency trades, and it is the reason to insist on physics-first explanations: the physics is what the marketing cycle cannot change.
A Decision Framework for 2026
The guidance I actually give, by situation, triangle in hand.
If you are building an application, start with a boring, excellent operational database, which in 2026 means Postgres or its managed equivalents, and resist every temptation to make it also be your analytics. Its job is the current state of the business, guarded jealously.
The moment real analytical questions arrive, and they arrive earlier than teams expect, give them an analytical home rather than a read replica with delusions: at small scale that can be as light as an embedded engine over Parquet exports, and at any serious scale it is the open lakehouse, fed by the least-engineering path available to you, a managed zero-ETL integration where your stack offers one, a CDC platform where it does not, with the maintenance discipline, compaction, snapshot expiration, monitoring, budgeted from day one.
Choose your freshness honestly, per workload, with a named stakeholder and a number attached: most "real-time" analytical requirements dissolve into minutes, which the modern pipeline delivers cheaply, genuine seconds-level needs justify the streaming stack, and the questions that truly require this-instant operational truth should be answered by the operational side itself, through federation with guardrails, rather than by chasing replication lag to zero.
Consider the integrated platforms, HTAP survivors and lakebase-style offerings alike, when their specific bargain fits: one-system simplicity at moderate scale, or deep single-vendor integration in exchange for concentration you accept with eyes open. And whatever you compose, put the open substrate underneath and the governed surface on top: Iceberg as the analytical storage everyone can read, a catalog governing access and, increasingly, both sides' metadata, and the semantic layer giving humans and agents one meaning across the divide, because the seam between operational and analytical is exactly where definitions drift and agents fall in.
Which is the closing point the whole article has been walking toward: the population that most needs this divide healed is not analysts, who learned to live with it decades ago, but AI agents, whose single tasks routinely need current state and historical context together, the customer's balance now and their behavior over two years, one door, one governance model, one set of definitions. Every development this article surveyed, zero-ETL, lakebase architectures, federation under governed catalogs, is converging on serving exactly that consumer, and the architectures that win the agent era will be the ones that made the divide invisible without lying about the physics underneath.
A Worked Example: One Company, Four Architectural Eras
Watch the whole article play out in one composite company, a retailer whose data architecture evolves through the eras in fast forward, because the sequence is nearly universal even when the timeline varies.
Era one, the founding years: one Postgres database does everything, applications and analytics alike, and it works, because at small scale everything works. The first reports run as SQL against production, the first dashboard follows, and the era ends the way it always ends: a Black Friday morning when the marketing team's cohort query and the checkout path meet in the buffer pool, and the CTO learns the word "anti-pattern" from an incident review. First response: a read replica, which buys a year of peace and quietly teaches the wrong lesson, that analytics is a replication problem rather than a physics problem, right up until the replica, still a row store, buckles under the scan load its layout was never shaped for.
Era two, the classical split: the company stands up a proper analytical home, in the modern version an Iceberg lakehouse on object storage, and builds pipelines, nightly batch at first, then hourly. The anti-pattern incidents stop, the analytical estate flourishes with two years of history the operational side never kept, and the classical costs arrive on schedule: the finance dashboard is always a day behind, the pipeline team becomes a permanent line item, the customer-360 project discovers three definitions of "active customer" across the seam, and every executive asks, at least once a quarter, why the numbers cannot just be live.
Era three, the repricing: CDC replaces batch, operational changes now land in Iceberg tables in seconds through the streaming machinery, whether a managed zero-ETL integration or a CDC platform, with the maintenance discipline, compaction, delete handling, budgeted properly this time. Freshness complaints evaporate for every workload that honestly needed minutes or seconds, which is nearly all of them. The genuinely operational questions that remain, what is this order's status right now, for this customer on the phone, get answered the right way: federated queries against the operational side through the governed access layer, with workload guardrails in place, rather than by chasing replication lag to zero. And the governance seam closes from above: one catalog governing the lakehouse tables and, through federation, the operational sources, one semantic layer defining "active customer" once for both worlds.
Era four, the frontier the company is entering now: agents arrive, and their tasks straddle the divide by nature, check this customer's current cart, compare against their two-year pattern, act. The composed architecture handles it through the one governed door, MCP surface, catalog-enforced access, semantics shared across the seam, and the platform team is piloting the shared-substrate options, a lakebase-style Postgres whose storage lives beside the lakehouse's, for the new agent-facing applications where one copy and branching databases per agent experiment are genuinely compelling, benchmarked against their real transactional profile rather than the launch keynote. The divide, at this point, has not been eliminated anywhere in the stack. It has been made invisible to every consumer, human and agent, which was the achievable promise all along.
Four eras, and the lesson the composite is built to carry: every company walks this road, the only variables are how many incidents each transition costs, and the teams who know the physics in advance buy the same destination for a fraction of the tuition.
Questions I Hear Most Often
Is the OLTP versus OLAP distinction still real, or is it legacy thinking? The workload distinction is as real as ever, it is five forks of physics, and what has genuinely blurred is the system boundary: seconds-level replication, shared storage substrates, and federated access mean the two sides can feel like one estate. Distinguish the claims carefully: "the divide is invisible" is achievable engineering, "the divide is gone" is marketing, and the anti-patterns section is what happens to teams who believe the second version.
Can Postgres just be both, with extensions? Further than ever, and within limits worth respecting: replicas, columnar extensions, and the new Iceberg-bridging extensions let a Postgres estate serve real analytical load at moderate scale, and it remains a row store with row-store physics underneath. The honest pattern the extensions enable is better described as Postgres joining the composed architecture, writing to and reading from the open analytical substrate, than as Postgres replacing it.
What about DuckDB and the embedded analytical wave? A genuinely important development that fits the framework rather than breaking it: embedded columnar engines make the analytical side radically cheaper to instantiate, per laptop, per service, per agent, which lowers the scale at which "give analytics its own home" makes sense to nearly zero. The divide persists, the barrier to respecting it collapsed.
Do streaming systems belong to OLTP or OLAP? Neither and between: streams are the divide's connective tissue, the movement layer between the two estates, and stream processors do operational-shaped work on analytical-shaped flows. The cleanest mental model keeps three estates, operational state, streams of change, analytical history, with the second existing to reconcile the first and third continuously.
Is lakebase-style convergence going to eliminate zero-ETL and CDC? Directionally it shrinks them, one copy needs less copying, and practically the two-engine, replicated pattern will dominate for years: it is mature, composable across vendors, and its trade-offs are known. Watch the shared-substrate architectures with real interest and benchmark them against your actual transactional profile before believing any "no trade-offs" framing, including the ones that will be made about open implementations I am rooting for.
What is the single most common mistake you see? Letting the divide be decided by default instead of by design: the startup that never gives analytics a home until the production database is on fire, and the enterprise that pipelines everything everywhere without asking which workloads needed to move at all. The physics gives you the forks, the triangle gives you the trade, and the architecture should be able to say, workload by workload, which choice it made and why. That sentence is the whole discipline.
Closing Thoughts
The operational-analytical divide is the oldest structure in data architecture because it is the truest: two kinds of question, two shapes of workload, five forks of physics, and no engine that sits in the middle without paying everywhere. Thirty years of unification promises did not erase it, and the past two years did something better, they repriced it: replication in seconds, analytical homes at every scale, shared open substrates under both sides, and governance that can finally span the seam. The divide's future is not elimination. It is invisibility, honestly engineered, and the architects who thrive will be the ones who can see the seam precisely while building systems where nobody else has to.
If you want the full foundation under that work, the storage physics, the formats, the streaming machinery, the catalogs and semantics that govern the seam, that is what my books are for. I co-authored Apache Iceberg: The Definitive Guide and Apache Polaris: The Definitive Guide for O'Reilly, with further titles on lakehouse architecture, data engineering, and agentic analytics.
Browse the full collection of my books on data and AI at books.alexmerced.com.