Optional: Modern Big Data Economics
Concept. Modern data systems lower cost by keeping simple workloads in PostgreSQL, loading raw data before transforming it, and separating inexpensive storage from on-demand compute. At scale, teams add specialized systems and use raw SQL when abstractions hide expensive or unsafe behavior.
Intuition. A startup can run one managed PostgreSQL database for $10 to $100 a month. A 100 TB analytics workload can instead keep files in object storage and rent compute only while a query runs.
This optional exploration follows the SQL Introduction and examines how Big Tech pays for scale.
Four costs that shape the modern data stack
Once you can write SQL, the next question is what it costs to run at scale. Four trends shape that bill.
Trend 1: Specialize only when scale requires it
-
Startup: Run managed PostgreSQL for $10 to $100 a month through AWS, GCP, Supabase, or Neon. Add a
JSONBcolumn for flexible, semi-structured data instead of operating a separate NoSQL system. -
Big Tech: Run a hybrid stack: an OLTP database, an OLAP warehouse, an ELT pipeline, and NoSQL stores as needed. Managed services and custom engines add a specialization tax. At Big Tech scale, building and operating every component by hand would be prohibitively expensive.
Figure: Basic Postgres plus a JSONB column goes a long way, versus spinning up specialized systemsTwo ways to run a data stack. Left (cyan), the simple default: basic Postgres, stable and proven, with a JSONB column added for flexible, semi-structured data, so one database holds both the typed columns and a JSON object right in the row, and a managed provider like AWS, GCP, Supabase, or Neon runs it for ten to a hundred dollars a month. Right (grey), the specialization tax: a hybrid stack of specialized systems, an OLTP database, an OLAP warehouse, an ELT pipeline between them, and NoSQL stores as needed, plus managed services and custom engines, which Big Tech pays only because at their scale doing it by hand would bankrupt them. A bar underneath reads that one Postgres plus JSONB goes a long way, so you specialize only when scale forces it. Color key: cyan is basic Postgres plus a JSONB column, grey is the specialized systems scale eventually forces.
Figure 1. Basic Postgres plus a JSONB column supports typed columns and semi-structured fields in one row and keeps them queryable with SQL. A managed provider like AWS, GCP, Supabase, or Neon runs this setup for ten to a hundred dollars a month. Big Tech runs a hybrid stack: an OLTP database, an OLAP warehouse, an ELT pipeline, and NoSQL stores as needed, plus managed services and custom engines.
Trend 2: Load before you transform
ELT loads raw data into inexpensive object storage such as S3 or GCS, then transforms it with SQL. ETL transforms the data before loading it.
-
Keeping raw data lets a team rerun transformations after fixing a bug.
-
Storage and management costs have fallen by orders of magnitude over the past decade. In the 2020s, BigQuery storage costs under $10 per TB each month.
-
Loading first also makes streaming data easier to handle and supports real-time processing with SQL.
Figure: The ETL to ELT flip: transform moves from before the load to after itTwo pipelines showing the flip in the order of work. Top (grey), the old ETL way: Extract, then Transform to clean the data, then Load the clean result, so you clean before you store. Bottom (cyan), the new ELT way: Extract, then Load the raw data straight into cheap object storage like S3 or GCS, then Transform to clean it later with SQL, so you store raw first and clean later. Transform moves from the middle to the end. A bar underneath explains why now: storage costs about ten dollars per terabyte per month, so you keep the raw data and re-run the logic anytime a bug shows up. Color key: grey is the old ETL order, transform before load; cyan is the new ELT order, load raw then transform.
Figure 2. ETL runs Extract, Transform, then Load. ELT runs Extract, Load raw data into object storage, then Transform with SQL. Storage at about ten dollars per terabyte per month makes it feasible to keep every raw row and re-run transforms after a bug.
Trend 3: Separate storage from compute
A coupled architecture ties storage to an always-on compute cluster. Holding 100 TB therefore incurs CPU and RAM costs even when queries run only once a week.
A decoupled architecture keeps data in object storage such as S3 and starts compute only while queries run. Storage can grow almost without limit at low cost, while compute scales independently with query demand.
Raw data lands as columnar Parquet files in object storage and receives structure at query time, or schema-on-read. This is a data lake. A table format such as Apache Iceberg tracks schema, file membership, and snapshots across those files. It adds schema evolution, time travel, and ACID table semantics. Together, object storage and table semantics form a lakehouse.
Figure: Coupled versus decoupled storage and compute: pay for an idle 24/7 cluster, or pay per queryTwo panels. Left, the coupled legacy architecture (grey): one always-on cluster holds 100 TB with its CPU and RAM bolted together, billed 24/7 even though the data is queried about once a week, so you pay a premium for idle hardware. Right, the decoupled architecture (cyan): raw data sits in dirt-cheap object storage like S3 or GCS that scales to infinity for pennies, and an ephemeral compute engine spins up only for the few minutes a query runs, then shuts off. Splitting them lets you scale storage and compute independently, the foundation of data lakes, where the raw data is Parquet files in object storage and a table format like Apache Iceberg makes them queryable as one table. Color key: grey is the coupled always-on cluster that pays for idle capacity, cyan is the decoupled storage-plus-ephemeral-compute model.
Figure 3. A coupled cluster ties 100 TB to always-on CPU and RAM and bills 24/7, even with weekly queries. A decoupled system stores raw data in object storage and rents compute only for the minutes a query runs.
Trend 4: Know what the ORM hides
An ORM such as SQLAlchemy maps Python objects to database rows, which lets developers build features without writing SQL.
-
Startup: The ORM speeds development.
-
At scale: Hidden behavior can issue redundant queries or cause silent failures that corrupt data across distributed machines.
CS145 teaches raw SQL so you can decide which operations can stay behind an ORM and which require direct control.
Figure: The ORM scale wall: an object-relational mapper wins in the startup phase and hits a wall at scaleTwo panels showing the same tool at two stages. Left, the startup phase (cyan): an ORM like SQLAlchemy turns Python objects into database rows with no SQL, so you ship features in minutes, and it hides the details. Right, the scale phase (amber, a caution): across many users and distributed machines those same hidden details cause silent failures that can corrupt data, so you need the control of raw SQL. The lesson is that the ORM trades control for speed, which is a good deal early and a liability at scale. Color key: cyan is the startup win where the ORM saves time, amber is the caution at scale where its hidden details become dangerous.
Figure 4. An ORM maps Python objects to rows without SQL. In distributed systems, hidden ORM behavior can issue redundant queries and corrupt data without an obvious failure signal. Raw SQL knowledge supports a deliberate split between ORM code and handwritten queries.
Takeaway: Start with the simplest database that fits the workload. Add ELT, decoupled compute, specialized stores, and raw SQL control when scale makes their cost worthwhile.