The cloud questions every provider asks, without the provider: object storage, warehouses, serverless or clusters, identity and secrets, streams and CDC, cost and releases. Each answer names the AWS, GCP and Azure service for it.
Where the files live, how they are laid out, and what they cost to keep.
Compute and query engines
4
What runs the work, how it is billed, and how to stop paying for idle machines.
Access and security
4
Who and what may read the data, where the secrets live, and how sensitive columns stay hidden.
Getting data in
4
Streams, database changes and file loads, and how each one goes wrong.
Running it: schedules, alerts, cost, releases
4
Orchestration and monitoring, a bill that doubled, and getting a change safely to production.
01 / 20
Reported · 3Object storage & lake layout
Data lakes on every cloud sit on object storage: Amazon S3, Google Cloud Storage, or Azure Data Lake Storage Gen2. Why is that? What does object storage not do that a normal file system does?
Why they ask this
It checks that you know what your data actually sits on. Many pipeline bugs — half-written outputs, slow listings, renames that take hours — come from treating a bucket like a local disk.
Say this
Object storage is cheap, scales without planning and is very durable, and every engine can read it, so storage and compute are paid for separately. But it stores whole objects by key: there are no real folders, no editing or appending in place, and on S3 a "rename" is a copy plus a delete, so a job writes to a new path and publishes the result in one step.
The reasoning
A data lake has to hold years of files for many engines — Spark, a warehouse, a query service — at a low price. Object storage gives exactly that: you pay per gigabyte stored and per request, it grows without capacity planning, and the providers design it for very high durability by keeping copies across devices and zones. Because the files are separate from any cluster, you can switch the cluster off and the data stays.
What it does not give you is a file system. An object is written whole and replaced whole; you cannot append a line to it or change a byte in the middle. "Folders" are only key prefixes, so listing a large prefix is slow and costs requests. On S3, and on Cloud Storage buckets without the hierarchical namespace option, renaming a "folder" of 10,000 files is 10,000 copies and 10,000 deletes, not one quick step. ADLS Gen2 with the hierarchical namespace turned on is the exception: it has real directories with atomic renames, which is one reason Azure lakes use it.
For a pipeline this means: write each run to a new, unique path (one folder per run or per date partition), check it, then switch readers to it in one step — through a table format such as Delta Lake or Iceberg, a catalog update, or a success marker file. Never overwrite files that readers are reading. S3 has had strong read-after-write consistency since December 2020, so the old "the listing is out of date" problem is gone; the lack of atomic changes across many files is not.
The answer most people give
"It is just a big shared hard drive." That belief leads to jobs that rename output folders, append to files and overwrite paths dashboards are reading — jobs that break or slow down as the data grows.
They’ll ask next
Your Spark job writes 2,000 files and fails after 1,200. What do readers see, and how do you design the write so they never see half a result?
Reported · 3Object storage & lake layoutCost control
You design a new data lake in object storage for 5 TB of order data. How do you lay it out so queries read as little as possible? Say what you choose for folder structure, partitions, file format and file size.
Why they ask this
In the cloud you pay for what you scan and for every request. The layout decides both, so interviewers use this to see whether you think about speed and cost together.
Say this
Split the data into folders by the column most queries filter on — usually the date, as Hive-style folders such as event_date=2026-09-01 — store it in a columnar format such as Parquet, and keep files in the hundreds of megabytes, not kilobytes. A query on one day then reads one folder and only the columns it needs.
The reasoning
Partitioning puts rows into separate folders by a column value, for example orders/event_date=2026-09-01/. Athena, BigQuery external tables, Spark and Synapse serverless read the folder names and skip the folders the filter rules out. Choose the column almost every query filters on — usually a date — and keep the number of partitions sensible: partitioning by customer_id with millions of values creates millions of tiny folders and makes everything slower, not faster.
The file format matters as much. Parquet and ORC store data by column, compress it well and keep small statistics per block, so a query that needs 3 of 40 columns reads roughly those 3, and can skip blocks whose minimum and maximum cannot match the filter. CSV and JSON have to be read in full.
Then file size. Thousands of files of a few kilobytes each mean thousands of requests and a fixed overhead per file — the small-files problem — and streaming or very frequent loads cause it. Write bigger files, or compact the small ones on a schedule: OPTIMIZE in Delta Lake, or a job that rewrites a partition into fewer files. Files of roughly 100 MB to 1 GB are a good target for most engines.
The answer most people give
"Partition by every column people filter on." Partitioning on a column with many values, such as user_id, creates millions of tiny files, so every query lists and opens far more objects and becomes slower and more expensive.
They’ll ask next
A streaming job writes about 2 million files of 50 KB a day. How do you fix the reads without stopping the stream?
Reported · 3Storage classes & lifecycleCost control
A lake keeps raw files for 7 years. What are storage classes in cloud object storage: hot, cool, cold and archive? What does a lifecycle rule do to the cost of that lake?
Why they ask this
Most lakes keep raw data for years but read it for days. Interviewers want to hear that you match the storage class to how often the data is read, and that you know the catches.
Say this
Colder classes cost less to store per gigabyte but more to read, and most have a minimum storage time you pay for even if you delete earlier. A lifecycle rule moves objects to colder classes by age and deletes them when retention ends, so you set it once instead of moving files by hand.
The reasoning
Each cloud has the same ladder under different names. AWS S3 has Standard, Standard-Infrequent Access and the Glacier classes; Google Cloud Storage has Standard, Nearline, Coldline and Archive; Azure Blob Storage has the Hot, Cool, Cold and Archive tiers. Going down the ladder, the price to store a gigabyte falls while the price to read it — and sometimes the time to get it back — rises.
Two catches decide the design. First, minimum storage durations: Cloud Storage Nearline is charged for at least 30 days, Coldline 90 and Archive 365, and S3 Standard-IA for 30, so moving data you will delete next week into a cold class costs more, not less. Second, archive classes can take hours to restore, so they suit data you must keep for law or audit, not data an analyst may query tomorrow.
A lifecycle rule is a policy on the bucket: "after 30 days move to the cool class, after 90 to cold, after 365 to archive, delete after 7 years". For a lake read heavily for a week, sometimes for a quarter and almost never after a year, that cuts the storage bill a great deal without any code. Apply it to raw and log data; keep the curated tables that dashboards read in the standard class.
The answer most people give
"Move everything older than a week to archive to save money." Archive has slow restores and minimum storage charges, so the next backfill or audit becomes a long wait and a large retrieval bill.
They’ll ask next
Raw files are read heavily for 7 days, occasionally for 90, and must be kept for 7 years. Write the lifecycle rule.
Reported · 3Warehouses & query enginesCost control
A cloud warehouse such as Redshift, BigQuery or Synapse can store a 2 TB table itself. It can also read the same files in object storage as an external table. What is the difference between the 2? When would you use each one?
Why they ask this
It shows whether you know where your data is stored and what that does to speed and cost. Most teams query both kinds, so you will be asked when each makes sense.
Say this
A native warehouse table is loaded into the warehouse's own storage, which it organises for fast, repeated queries. An external table leaves the files in the lake and reads them at query time: no load step and one copy of the data, but usually slower and with fewer features. Use native tables for data dashboards query all day, and external tables for raw or rarely used data.
The reasoning
When you load data into a warehouse, it rewrites the data into its own storage format and keeps statistics, so it can prune, cache and spread the work well. BigQuery native tables, Redshift tables and Synapse dedicated SQL pool tables work this way. You pay for that storage and for the load, but repeated queries are fast and predictable.
An external table is only a definition — a schema and a location — over files in S3, Cloud Storage or ADLS. Athena, Redshift Spectrum, BigQuery external tables and Synapse serverless SQL pools read those files when the query runs. Nothing is copied, so the lake stays the single source and there is no load to keep in sync, but speed depends on the file layout and some features (caching, constraints, fast updates) are missing or limited.
A common pattern uses both: raw files and long history stay in the lake as external tables, while the cleaned and modelled tables that dashboards hit all day are loaded into native tables. The deciding questions are how often the data is queried, how fast the answer must be, and whether a second copy is worth its storage.
The answer most people give
"External tables are always cheaper because you do not store the data twice." If a dashboard scans those files hundreds of times a day, the repeated scans can cost far more than loading the data once into the warehouse.
They’ll ask next
Analysts query last month's orders every few minutes, but five years of history only for audits. Where does each one live?
Reported · 3Warehouses & query enginesCost control
Cloud warehouses such as BigQuery, Snowflake and Redshift on RA3 nodes separate storage from compute. What does that mean? Why does it matter for cost, and for 200 users querying at the same time?
Why they ask this
It is the main idea behind modern cloud warehouses, and it explains their pricing. Interviewers check that you can connect the architecture to the bill and to how many people can query at once.
Say this
The data lives in one shared, cheap storage layer, and the machines that run queries are separate and can be added, removed or paused. So storage is paid for all the time but compute only while it works, and extra compute can be added for busy hours or for another team without copying the data.
The reasoning
In an older warehouse the disks sat inside the nodes, so more data meant more nodes even if nobody queried it, and more users meant fighting over the same machines. With storage and compute separated, the data sits in a central storage service, and compute — clusters, warehouses or "slots" — reads from it.
Two things follow. Cost: storage is billed per gigabyte per month and compute per second or per query, and compute can be scaled down or paused at night. Concurrency: the BI team and the data science team can get separate compute on the same data, or the warehouse can add compute when many queries arrive at once — Redshift calls this concurrency scaling, BigQuery gives a query more slots, Snowflake starts extra clusters in a multi-cluster warehouse.
The trade-off is that data has to travel from storage to compute, so warehouses cache data near the compute and depend on columnar storage and pruning. Good layout — partitions, clustering, sort keys — still decides how much has to be read.
The answer most people give
"It means the warehouse is serverless, so cost is not a concern." Separation lets you control compute cost, but an unfiltered query or an always-on cluster still bills for every byte scanned or every hour it runs.
They’ll ask next
The BI team's morning dashboards slow down the data engineers' loads. How do you fix that on a warehouse that separates storage and compute?
Reported · 3Warehouses & query enginesCost control
Serverless query engines such as Amazon Athena and BigQuery on-demand bill per query. How are they billed? Why does the same question cost far more on a 1 TB CSV table than on a partitioned Parquet table?
Why they ask this
Pay-per-scan pricing turns one careless query into a real bill. Interviewers want to hear that you know what gets scanned and how to scan less.
Say this
They charge by the amount of data the query reads, not by the rows it returns or the time it takes. A filter on the partition column lets the engine skip whole folders, and a columnar format lets it read only the columns used, so the same answer can scan a small fraction of the data.
The reasoning
Athena charges per terabyte scanned, with a 10 MB minimum per query, and BigQuery on-demand charges per tebibyte processed. A LIMIT 10 at the end does not reduce the scan: the engine still reads everything the query needs before it can return ten rows.
Three things cut the scan. Partition pruning: if the table is split into date folders and the query filters on that date column, only those folders are read. Column pruning: in Parquet or ORC, selecting 3 columns reads roughly those 3, while SELECT * reads them all — and in CSV every query reads every byte of every row. Compression: columnar files compress well, and the engine bills the bytes it actually reads.
Watch the trap: the filter must be on the partition column itself. A BigQuery table partitioned on event_date but queried with WHERE DATE(event_ts) = '2026-09-01' can read every partition. For predictable spend, teams also set limits — a maximum bytes billed per query in BigQuery, workgroup limits in Athena — or move to reserved capacity when usage is steady.
The answer most people give
"Add LIMIT 100 so the query is cheap." LIMIT stops the output, not the scan: you still pay for every byte the query had to read.
They’ll ask next
A daily-partitioned 40 TB CSV table is shared by 300 analysts. Which three changes cut the bill the most?
You have 2 jobs. A 50 MB JSON file arrives every 10 minutes. A 2 TB join runs nightly. When do you run a transformation as a serverless function, such as AWS Lambda? When do you run it as a Spark job on Glue, Dataproc or Databricks?
Why they ask this
Choosing the compute for a load is everyday cloud work. The interviewer checks that you know the limits of functions and the overhead of clusters.
Say this
Functions suit small, short, event-driven work: a 50 MB file every 10 minutes fits easily. They have hard limits on run time and memory — AWS Lambda stops at 15 minutes and offers at most about 10 GB of memory. A 2 TB join needs many machines working together, so it belongs in a distributed engine such as Spark.
The reasoning
A serverless function starts on an event (a file lands, a message arrives), runs your code and stops. You pay per call and per second of memory, there is nothing to manage, and it starts quickly. That makes it good for small parsing, validation, moving and routing work. The limits are real: each function has a capped run time and memory (on AWS Lambda, 15 minutes and up to 10,240 MB), runs on one machine, and at high volume many small calls can cost more than one steady job.
Spark, through Glue, EMR, Dataproc or Databricks, splits the work across many machines and moves data between them, which a join of two large datasets needs. Starting compute takes time and has a minimum charge, so it is wasteful for a 50 MB file but right for terabytes.
So for the example: the 50 MB JSON every 10 minutes goes to a function (or a small serverless job) that validates it and writes Parquet to the lake; the nightly 2 TB join runs as a Spark job, ideally on serverless Spark or on a cluster created for the run and removed afterwards.
The answer most people give
"Use Lambda for everything because it is serverless and cheap." A 2 TB join does not fit one function's time and memory limits, and splitting it by hand across thousands of functions rebuilds a worse Spark.
They’ll ask next
Your function sometimes receives a 3 GB file instead of 50 MB. What do you change so it does not time out?
Your nightly Spark jobs run for 2 hours on a managed cluster that stays on all day. It could be EMR, Dataproc or Databricks. How do you stop paying for idle machines? When is serverless Spark the better choice?
Why they ask this
Idle clusters are one of the most common reasons a cloud data bill is high. Interviewers want practical fixes, not only "use spot instances".
Say this
Create the cluster for the job and delete it when the job ends — an ephemeral or job cluster — set auto-termination on anything interactive, and let workers autoscale. Serverless Spark (Glue, EMR Serverless, Dataproc Serverless, Databricks serverless) removes cluster management altogether and suits jobs that run a few times a day.
The reasoning
A cluster that runs 24 hours for a 2-hour nightly job bills 22 idle hours. The standard fix is an ephemeral cluster: the orchestrator creates the cluster, runs the job and deletes the cluster — also when the job fails. On Databricks the same idea is a job cluster instead of an all-purpose cluster, which is also cheaper per unit. Clusters people use interactively should shut down by themselves after a period with no activity.
Within a run, autoscaling adds workers when there is work and removes them when there is none, and spot or preemptible machines lower the price of workers whose loss Spark can retry. Keep the driver on a normal machine, because losing it fails the job.
Serverless Spark goes one step further: you submit the job and the service provides and removes the machines. It suits scheduled jobs that do not need a tuned, long-lived cluster. A cluster you manage still makes sense when you need special libraries, steady performance or many jobs back to back.
The answer most people give
"Use a bigger cluster so the job finishes faster and costs less." A bigger cluster that stays on after the job still bills every idle hour; the waste is the idle time, not the size.
They’ll ask next
The job fails at 3 a.m. How do you make sure the ephemeral cluster is still deleted?
A pipeline job must read 1 bucket and write to the warehouse. No password or access key may sit in the code. How does the job get permission on AWS, on GCP and on Azure?
Why they ask this
Access is the first security question in most cloud loops. Interviewers check that you use identities and roles, not shared keys, and that you grant the least access needed.
Say this
Give the job its own identity — an IAM role on AWS, a service account on GCP, a managed identity on Azure — and attach a policy that allows only what it needs, such as reading one bucket prefix and writing one schema. The cloud gives the job short-lived credentials at run time, so no long-lived key sits in the code.
The reasoning
In the cloud, people and programs are both identities, and permissions are attached to identities through policies or role assignments. A pipeline should not borrow a person's account or a static access key. Instead, a Glue job or an EMR cluster assumes an IAM role, a Dataflow or Dataproc job runs as a service account, and Data Factory or a Databricks workspace uses a managed identity. The platform gives the job temporary credentials that expire and rotate on their own.
Least privilege means the policy allows only the actions and resources the job needs — "read objects under s3://lake/raw/orders/" rather than "full access to S3". A separate identity per pipeline keeps a bug or a leak in one job from reaching everything, and the audit logs then show which job did what.
Two details often come next. On Azure there can be two layers: RBAC roles control access to the storage account, and ACLs on ADLS Gen2 folders control access inside it. And encryption keys are resources too: a job that reads data encrypted with your own key also needs permission to use that key.
The answer most people give
"Create an access key for a service user and put it in the job's config." Long-lived keys get copied into repos and logs, never expire on their own, and make it impossible to tell which job used them.
They’ll ask next
A job must write to one folder in the lake and read nothing else. Write the permissions you would give it.
Reported · 3Identity & accessEncryption & sensitive data
Your pipelines connect to a partner database with a password, and to a SaaS API with a key. Both are pasted into 12 job configs and notebooks. Where should those secrets live in the cloud? How do you move them out?
Why they ask this
Credentials leaked from code are a common real incident. The interviewer checks that you know the cloud's secret store and how a job reads from it at run time.
Say this
Put them in the cloud's secret store — AWS Secrets Manager (or Parameter Store), Google Secret Manager, Azure Key Vault — and let each job read them at run time with its own identity. Then rotate every secret that was ever in code, because it is still in the history.
The reasoning
A secret store keeps secrets encrypted, controls who may read each one, logs every access and can rotate some secrets automatically. The job's identity (role, service account or managed identity) gets permission to read only the secrets it needs. Airflow secrets backends, Data Factory linked services and Databricks secret scopes can all point at the store instead of holding the value.
Moving out is a small project: list every place a secret appears (configs, notebooks, environment variables, the repo history), create each one in the store, change the code to fetch it, and give each job identity read access to only its secrets. Then rotate every secret that was ever written in code, because old commits and logs still contain the value.
Where you can, remove the secret altogether: connecting to cloud storage or a cloud database with the job's own identity needs no password at all. And secrets must never be printed in logs — mask them in the orchestrator.
The answer most people give
"Move the passwords into environment variables and you are done." The values are still visible to anyone who can read the job definition, nothing rotates them, and the old ones remain in the repo history.
They’ll ask next
A key was committed to a public repository an hour ago. What do you do, in order?
A pipeline moves 200 GB of customer data a day between a bucket and a warehouse. What do encryption at rest and encryption in transit protect against? When would you use your own keys in a key management service instead of the provider's default keys?
Why they ask this
Companies with financial or health data ask this in almost every loop. It checks that you know what is on by default and what you still have to decide.
Say this
At rest protects stored data on disks and in buckets; in transit (TLS) protects data moving over the network. The big clouds now encrypt storage by default with keys they manage. You use customer-managed keys when you must control and audit who can use the key, rotate it on your own schedule, or make data unreadable by disabling the key.
The reasoning
Encryption at rest means the stored bytes are encrypted, so a lost disk or a copied file is useless without the key. S3, Cloud Storage, Azure Storage and the cloud warehouses encrypt data at rest by default. Encryption in transit means connections use TLS, so the data cannot be read on the network; you make sure every client — database drivers, APIs, JDBC connections to the warehouse — uses it.
With provider-managed keys you get encryption with no work, but you do not control the key. A customer-managed key lives in a key management service in your account: you decide who may use it, every use is logged, you set the rotation, and disabling it makes the data unreadable. Regulated companies often require this for sensitive data — and jobs then also need permission to use the key.
Encryption does not replace access control. If a user or a job may read the table, the platform decrypts the data for them. Hiding sensitive columns from people who can read the table needs masking, column-level permissions or tokenisation, which is a separate question.
The answer most people give
"The data is encrypted at rest, so analysts cannot see the card numbers." Anyone allowed to read the table sees decrypted values; hiding columns takes masking or column-level access, not encryption.
They’ll ask next
Legal says a customer's data must become unreadable on the day their contract ends. How does a customer-managed key help?
Reported · 3Identity & accessEncryption & sensitive data
Analysts from 3 teams query a `customers` table. Only the risk team may see card numbers and dates of birth. The India team may see only Indian customers. How do you enforce that in a cloud lake or warehouse?
Why they ask this
Handling personal data comes up in nearly every loop, and "give each team its own copy" is the answer that fails. The interviewer wants column and row controls on the data itself.
Say this
Use the platform's fine-grained access control: column permissions or masking policies for the sensitive columns, and a row filter for the country rule, granted to groups rather than people. On AWS that is Lake Formation, on GCP BigQuery policy tags and row access policies, on Azure Unity Catalog column masks and row filters, or row- and column-level security in Synapse.
The reasoning
Copying the table into one version per team works for a week and then drifts: the copies go stale, and someone forgets to filter a new column. Fine-grained access control keeps one table and decides what each reader sees.
For columns, you either deny the column (the risk team sees it, others get an error or do not see it) or mask it (others see the last four digits or a hash). AWS Lake Formation grants columns and rows on Glue catalog tables for Athena, Redshift Spectrum and EMR; BigQuery uses policy tags on columns and row access policies on rows; Databricks Unity Catalog has column masks and row filters; Synapse dedicated SQL pools support column-level and row-level security.
For rows, a row filter keeps only the rows where country matches what the reader is allowed. Grant both rules to groups (risk_team, india_analysts), not to named people, so joining or leaving a team is only a change of group. Test by querying as a member of each group, and keep the audit logs.
The answer most people give
"Create a view for each team without the sensitive columns." Views help, but if people can still read the base table they can query it directly, and one view per team per rule multiplies fast; the control has to sit on the data itself.
They’ll ask next
A new column, phone_number, is added next month. How do you make sure it is protected from the first day?
A managed stream receives 15,000 events a second of about 2 KB each. It could be Kinesis Data Streams, Azure Event Hubs or Google Pub/Sub. What do the shards or partitions decide? What does the partition key or ordering key decide?
Why they ask this
Streams are sized and ordered by their partitions. The interviewer checks that you can size a stream and know which order you do and do not get.
Say this
Partitions — shards in Kinesis — are the units of throughput and of order: each one takes a fixed write rate and keeps its events in order. The key decides which partition an event goes to, so events with the same key stay in order while different keys are read in parallel. Pub/Sub hides partitions and offers ordering keys instead.
The reasoning
A Kinesis shard accepts up to 1 MB or 1,000 records a second for writes. 15,000 events a second at 2 KB each is about 30 MB a second, so provisioned mode needs at least 30 shards — or on-demand mode, which adds shards for you. Event Hubs partitions work the same way, and each consumer reads a partition in order and records its position (an offset or sequence number).
The partition key is hashed to choose the partition. Use a key whose events must stay in order, such as device_id or order_id: all events for that key land in one partition, in order. A poor key — one value for most events — sends everything to one partition, which then throttles while the others sit idle. That is a hot partition.
Pub/Sub has no partitions to manage: it scales by itself and does not keep order by default. With an ordering key, messages that share the key are delivered to a subscriber in order. In every one of these services, order holds only within one key or partition, never across the whole stream.
The answer most people give
"The stream keeps all events in order." Order holds only within a partition or an ordering key; consumers reading many partitions at once see events from different keys mixed together.
They’ll ask next
One customer sends 40% of all events, and their partition is throttled. What do you change?
A managed stream, such as Pub/Sub, Kinesis or Event Hubs, delivers messages at least once. After a consumer restart, about 2% of 1 hour's payment rows in the warehouse are duplicates. How did they get there? How do you stop them?
Why they ask this
Almost every streaming loop asks this. It checks that you expect redelivery and make the write idempotent, instead of hoping for exactly-once.
Say this
At-least-once means a message is sent again if its acknowledgement or checkpoint was not saved — for example when the consumer crashed after writing but before acknowledging. Give every event a unique id and write idempotently: deduplicate on that id, or MERGE on it, so a second delivery changes nothing.
The reasoning
A consumer usually writes the event and then acknowledges it, or checkpoints its position. If it crashes between the two, the service believes the message was never handled and delivers it again, so it is written twice. Producer retries can create duplicates too. This is normal behaviour, not a bug in the service.
The fix is on the writing side. Each event needs a stable unique id from the producer (a payment_id or event_id, not the arrival time). Then either write with an upsert keyed on that id (MERGE into the table), or land everything in a raw table and build the clean table with a step that keeps one row per id — for example ROW_NUMBER() over the id. Some services offer exactly-once inside their own pipeline, such as Pub/Sub exactly-once delivery or Dataflow's exactly-once processing, but once data crosses into another system you still need the idempotent write.
To clean up what is already there, run the same deduplication over the affected hour and replace that hour's partition. Then add a check that counts duplicate ids in each load, so the next time is caught at once.
The answer most people give
"Switch the stream to exactly-once and the problem is gone." Exactly-once inside one service does not cover the write into your warehouse; a crash between writing and acknowledging still duplicates the row there.
They’ll ask next
The producer puts no unique id on events. How do you build one, and what can go wrong with it?
You must bring a 500 GB operational database, such as MySQL or PostgreSQL, into the cloud warehouse. You use a managed service such as AWS DMS or Google Datastream. How does the first full copy work? How do only the changes arrive after that?
Why they ask this
Database ingestion is the first job many data engineers get. The interviewer checks that you know full load versus CDC and what the source database must have switched on.
Say this
Start with a full load of each table, then keep it current with change data capture (CDC): the service reads the database's change log and sends every insert, update and delete. The source must keep that log — binary logging in row format on MySQL, logical replication on PostgreSQL, supplemental logging on Oracle — and the target applies the changes in order with a merge.
The reasoning
A full load copies every row once. For big tables it runs in parallel and can take hours while the database keeps changing, so CDC starts from the point in the log where the full load began; the changes made during the load are applied on top, and nothing is lost.
Log-based CDC reads the database's own transaction log instead of querying the tables, so it catches deletes and every change without loading the source. It needs settings on the source: binary logging in ROW format on MySQL, logical replication on PostgreSQL, supplemental logging on Oracle, and enough log retention for the service to catch up after a pause. The query-based alternative — select rows whose updated_at is newer than the last run — is simpler, but it misses deletes and depends on that column always being set.
On the target, changes usually land in a raw table with the operation type and a sequence number, and a MERGE applies them to the current table: insert new keys, update changed ones, delete removed ones, always applying the latest change per key. Watch the replication lag, so you know how far behind the warehouse is.
The answer most people give
"Copy the tables every night with SELECT * and overwrite." It works for small tables, but it reloads everything, misses changes that happen and are undone between runs, and puts heavy load on the production database.
They’ll ask next
The CDC task stopped for a day, and the source keeps only 12 hours of log. What now?
A 5 GB batch file lands in object storage every day and must go into the warehouse. What are the ways to load files into a cloud warehouse? Think of `COPY` in Redshift, a load job in BigQuery, or `COPY INTO` in Snowflake. Which one do you use for this daily batch?
Why they ask this
Loading is where many pipelines spend their time and money. Interviewers check that you choose the bulk path for batches and know how to make a reload safe.
Say this
For a daily batch use the warehouse's bulk load from object storage — COPY, a load job, COPY INTO: it reads many files in parallel and costs little next to row-by-row inserts. Load into a staging table, check it, then swap or merge it into the target, so rerunning the same day does not duplicate rows.
The reasoning
Bulk load commands read files straight from S3, Cloud Storage or ADLS and spread them across the warehouse's compute. They work best with many medium-sized, compressed or columnar files rather than one huge CSV, because each file can be read in parallel. In BigQuery, batch load jobs from Cloud Storage are free — you pay for the stored data — while streaming inserts are charged.
Streaming inserts, or a streaming write API, make rows available within seconds and are for real-time needs. For a daily 5 GB file they cost more and add nothing.
The load must be safe to run twice. Load the day's files into a staging table, check them (row count against the source, no nulls in keys, no duplicates), then publish: replace that day's partition in the target, or MERGE on the business key. If the job fails halfway, you rerun it and get the same result, not double rows.
The answer most people give
"Read the file in Python and INSERT the rows one by one." Row-by-row inserts into a columnar warehouse are slow and expensive; warehouses are built for bulk loads.
They’ll ask next
Yesterday's load failed after writing 60% of the rows. Walk through the rerun.
Today a cron job on 1 virtual machine runs your 20 scripts every night. What does a managed orchestrator give you over that cron job? Think of Amazon MWAA, Step Functions, Cloud Composer or Azure Data Factory.
Why they ask this
Every pipeline needs scheduling. The interviewer checks that you know what goes wrong with cron as pipelines grow, and what orchestration adds.
Say this
Cron only starts scripts at a time. An orchestrator knows the dependencies between tasks, retries failures, waits for inputs, records every run with its logs, alerts on failure or lateness, and reruns or backfills a past day. The managed versions also run, patch and scale the orchestrator for you.
The reasoning
With cron, each script stands alone: if the extract fails, the transform still starts at 03:00 on yesterday's data, nobody is told, and there is no record of what ran. Rerunning last Tuesday means editing dates by hand.
An orchestrator models the pipeline as a graph — a DAG in Airflow, a pipeline in Data Factory, a state machine in Step Functions. Tasks run in order, a failure stops the tasks that depend on it, retries with a delay ride out short outages, sensors or triggers wait for a file or an upstream job, and every run is logged with its inputs. Backfilling or rerunning a date becomes a normal operation — as long as each task is idempotent.
The managed services — MWAA and Cloud Composer run Apache Airflow; Data Factory and Step Functions are the clouds' own — look after the servers, upgrades and scaling of the orchestrator. You still own the pipeline code, the alerts and the cost of what the tasks run.
The answer most people give
"Cron is enough; just leave gaps between the jobs." Time gaps hide dependencies: when one job runs long, the next one reads incomplete data and nobody notices.
They’ll ask next
A task failed at 03:00, and the table holds half of yesterday's rows. What does the orchestrator let you do that cron does not?
You run 30 scheduled jobs: warehouse loads, Spark jobs and 1 CDC task. The daily tables must be ready by 6 am. How do you monitor them on a cloud platform? How do you hear about a failed or late load before the business does?
Why they ask this
Silent failures are the most expensive kind. The interviewer checks that you watch freshness and the data, not only whether a job turned red.
Say this
Send every job's status and logs to the cloud's monitoring service (CloudWatch, Cloud Monitoring and Logging, Azure Monitor), alert on failures and on lateness against the 6 a.m. deadline, and add data checks — row counts, freshness, nulls in keys — so a job that "succeeds" with bad data also raises an alert.
The reasoning
First, failures: every job and task reports success or failure to one place, and a failure sends an alert, with a link to the logs, to a channel someone watches. Retries absorb short glitches so nobody is paged for them.
Second, lateness: a job that hangs never fails. Set a deadline alert — "if the orders table is not updated by 05:30, alert" — based on the table's last update time or the expected end of the run.
Third, the data itself: a run can succeed and load zero rows, or half. Add checks after each load — row count against the source or against yesterday, no duplicate keys, no nulls in required columns, values in range — and alert, or stop publishing, when one fails. A small dashboard of last run, duration and rows loaded per job shows slow drift long before it becomes a missed deadline.
The answer most people give
"Set up email alerts when a job fails." A hung job, or one that loads half the data, never fails — so the first alert is an angry message from the business at 9 a.m.
They’ll ask next
The CDC task is running, but its lag has grown to three hours. Which alert should have caught it?
The monthly cloud bill for your data platform went from $8,000 to $16,000. No new project was announced. Where do you look first? What are the usual causes?
Why they ask this
Cost questions are now standard in cloud loops. The interviewer checks that you start from data — the bill broken down by service and owner — rather than guessing.
Say this
Break the bill down by service, project and tag to find what grew, then by job or user. The usual causes are queries scanning far more data (a missing partition filter, SELECT * behind a new dashboard), clusters left running, a job stuck retrying, and storage that keeps growing because nothing expires.
The reasoning
Start with the provider's cost tools — Cost Explorer on AWS, billing reports and exports on GCP, Cost Management on Azure — and group the increase by service and by tag or project. Good tags (team, pipeline, environment) are what make this possible; if they are missing, adding them is the first fix.
Then go one level down. For query engines, list the most expensive queries and users from the query history (the INFORMATION_SCHEMA jobs views in BigQuery, the query history in Athena): a new dashboard that refreshes every 5 minutes with no partition filter is a classic. For compute, look for clusters running 24 hours, autoscaling that never scales down, or a job retrying all night. For storage, look for raw data with no lifecycle rule, many object versions, or a full copy written every day instead of an increment. Data transfer between regions, or out of the cloud, is another hidden cost.
Fix the cause and add a guard: budgets with alerts, per-query or workgroup byte limits, auto-termination on clusters, and lifecycle rules on buckets.
The answer most people give
"Buy reserved capacity so everything is cheaper." Reservations lower the price of steady use, but if the cause is a runaway query or an idle cluster, you just commit to paying for the waste.
They’ll ask next
One dashboard is half of the query cost. What do you change: the dashboard, the table, or the pricing model?
You move a pipeline from development to production on a cloud platform. It could be 1 Data Factory pipeline, 1 Airflow DAG or 1 Databricks job. How do you do it? How do you keep the development and production environments apart?
Why they ask this
Teams lose data when someone tests in production. The interviewer checks that you use separate environments, version control and an automated release.
Say this
Keep separate environments — ideally separate accounts, projects or subscriptions — for dev and prod, each with its own storage, identities and secrets. All pipeline code lives in Git, changes go through a pull request, and a CI/CD pipeline deploys the same code to each environment with that environment's settings.
The reasoning
Separate environments mean a test run cannot overwrite production tables or read production secrets. The cleanest split is a separate cloud account (AWS), project (GCP), or subscription or resource group (Azure) per environment, each with its own buckets, warehouse schemas, identities and secret store.
The code is the same everywhere; only configuration changes — bucket names, connection references, cluster sizes — passed in as parameters or environment settings. Everything lives in Git: Airflow DAGs and Databricks code as files, and Data Factory as the ARM templates a Git-connected factory publishes. A pull request is reviewed, tests run (unit tests on transforms, a check that the DAGs load), and a CI/CD pipeline deploys to dev, then to prod after approval.
Infrastructure — buckets, roles, clusters — is best created with infrastructure as code such as Terraform, so production can be rebuilt and every change is reviewed. Nobody edits production by hand; if someone must in an emergency, the change goes back into Git the same day.
The answer most people give
"Build in the production factory, but in a folder called test." Tests then run with production identities and can overwrite production data; one wrong parameter becomes an incident.
They’ll ask next
A hot fix is needed tonight. How do you ship it without skipping the process?