Google Cloud (GCP) Interview Questions · 2026

Google Cloud (GCP) Interview Questions (2026)

A platform engineer interviewing for a Series C logistics company in early 2026 got stuck on a question that wasn't about Kubernetes at all: why did a service account key checked into a CI pipeline two years ago still work, even though the engineer who created it had left the company. She'd run GKE clusters in production for three years and had never once had to reason about IAM outside clicking "add member" in the console. The interviewer wasn't testing whether she could deploy a pod. He was testing whether she understood that a long-lived service account key is a credential with no built-in expiry, and that the fix isn't rotating it faster, it's not creating it in the first place. Google Cloud is the third-largest public cloud by revenue, behind AWS and Azure, and it's the platform most closely tied to data and ML workloads at large enterprises, which is exactly why GCP interviews lean harder on IAM, networking, and data services than they do on compute trivia.

Here's an opinion that might be wrong: most GCP prep material spends its time on Compute Engine flags and gcloud command syntax because they're easy to quiz and easy to Google. Resource hierarchy, the way organization policies, folders, projects, and IAM bindings inherit and combine, is the thing that actually separates a candidate who's run GCP in a real company from one who's only ever spun up a single free-tier project. You can build a demo app for years without touching an organization node. You can't survive a security review at a company with more than one team without understanding how a deny policy at the folder level overrides an allow at the project level.

This page covers GCP interview questions across eight areas: compute (Compute Engine, GKE, Cloud Run, App Engine), storage and databases (Cloud Storage, Cloud SQL, Spanner, Firestore, BigQuery), IAM and security, networking (VPC, load balancing, Cloud NAT, Private Service Connect), Kubernetes on GKE specifically, data and pipeline services (BigQuery, Pub/Sub, Dataflow), operations and cost, and a closing set of architecture and edge-case questions. Commands are real gcloud and Terraform snippets, not pseudocode.

50Questions
Resource HierarchyCore Concept
gcloud + TerraformFormat
#3 by revenueCloud Rank

Compute: Compute Engine, GKE, Cloud Run, and App Engine

Almost every GCP loop opens with "which compute option would you pick and why," because the answer reveals whether a candidate actually reasons about trade-offs or just names services they've heard of.

Easy questions

9

Cloud Run is the default answer for a stateless HTTP service with unpredictable traffic. It scales to zero when there's no traffic, scales out per request automatically, and you pay only for the CPU and memory actually consumed during a request, not for idle capacity. Compute Engine only makes sense if you need control over the OS, custom kernel modules, or licensing that requires a specific VM image. GKE is worth the operational overhead once you have enough services that you need shared networking, custom scheduling, or sidecars that Cloud Run's simpler model doesn't support. App Engine Standard is the older version of "serverless HTTP," and most new projects pick Cloud Run over it now because Cloud Run supports any container, not just a fixed set of language runtimes.

The project ID is a human-readable, globally unique string you choose (or GCP generates) when creating a project, and it's what shows up in the console URL and most gcloud commands. The project number is an immutable, system-generated numeric identifier assigned at creation and never reused, even after the project is deleted. Most day-to-day gcloud and console work uses the project ID because it's easier to read and type, but some APIs and IAM conditions specifically require the project number because it's guaranteed never to be reassigned to a different project the way a deleted project's ID technically could be reused after enough time passes.

Cloud Storage has four classes, Standard, Nearline, Coldline, and Archive, that trade a lower per-GB storage price for a higher per-GB retrieval cost and a minimum storage duration. Nearline assumes access less than once a month with a 30-day minimum, Coldline assumes access less than once a quarter with a 90-day minimum, and Archive assumes access roughly once a year with a 365-day minimum. Any read of an object in one of these classes triggers the retrieval fee, and deleting or moving an object before its minimum storage duration is up still charges you for the remaining days as if it had stayed.

A signed URL grants time-limited access to a specific object without requiring the requester to have any Google Cloud identity or IAM permission at all, the signature itself, generated with a service account's private key, is the credential. Making a bucket public means anyone, forever, can read every object in it, with no expiry and no way to scope access to a single file or a single user's session.

text
gcloud storage sign-url gs://my-bucket/report.pdf 
 --private-key-file=key.json --duration=15m

Signed URLs are the right tool for letting a logged-in user download their own invoice or upload a file directly to storage without proxying the bytes through your app server.

Uniform bucket-level access applies a single IAM policy to every object in a bucket, so access is managed the same way as every other GCP resource, through IAM roles and bindings, with no per-object exceptions possible. The older fine-grained access model allows individual object ACLs on top of bucket-level IAM, which lets a specific object be more (or less) permissive than the bucket's own policy would suggest, a flexibility that also makes it much harder to audit who can actually read a given object without checking that object's ACL individually. Google recommends uniform access for new buckets specifically because it removes that audit gap.

The hierarchy runs Organization, then Folders (which can nest), then Projects, then individual resources within a project. IAM allow policies are additive down the hierarchy, a role granted at the organization level applies to every folder and project underneath it, and a principal's effective permissions are the union of every allow binding at every level above the resource being accessed. There's no way to remove a permission granted higher up by setting a more restrictive allow policy lower down, allow policies only ever add.

Cloud NAT provides outbound-only internet connectivity for resources that don't have an external IP, without exposing them to unsolicited inbound connections from the internet. A private GKE cluster's nodes intentionally have no external IPs for security reasons, but the containers running on them still need to reach the internet for things like pulling images from a public registry or calling an external API, so Cloud NAT sits in front of the VPC's default route to the internet and handles that outbound traffic.

text
gcloud compute routers nats create my-nat 
 --router=my-router --region=us-central1 
 --auto-allocate-nat-external-ips 
 --nat-all-subnet-ip-ranges

ClusterIP exposes a service only inside the cluster, on a virtual IP reachable from other pods, and is the default type. NodePort additionally exposes the service on a static port on every node's IP, reachable from outside the cluster if the node itself is reachable, but it's rarely used directly in production because it ties you to knowing node IPs. LoadBalancer type provisions an actual external cloud load balancer, a real billed GCP resource, in front of the service, and it's the only one of the three that shows up as a separate line item on your GCP bill.

An alerting policy defines a condition over a duration window, not a single data point, a metric has to stay above (or below) a threshold for the configured duration, five minutes, ten minutes, before the policy actually fires. This filters out a single noisy sample or a brief, self-resolving spike from turning into a page, while still catching a sustained problem within a reasonable window.

Medium questions

25

Live migration moves a running VM to a different physical host during planned host maintenance, host software updates, hardware failures the platform predicts in advance, without stopping the guest OS. Google documents this as the default behavior for standard VMs, migrating the instance's memory state across hosts while it keeps running (Google Cloud documentation, live migration process).

The instance experiences a short pause, typically well under a second, rather than a reboot. This is why a standard Compute Engine VM can have an uptime measured in months even though the underlying hardware gets touched regularly. It doesn't apply to preemptible or Spot VMs, which are designed to be reclaimed rather than migrated, and it doesn't help with an actual hardware failure that's already happened, only maintenance the platform can schedule ahead of time.

Both offer steep discounts, up to 60-91% off standard pricing depending on machine type, in exchange for Google being able to reclaim the instance with short notice. Preemptible VMs are the older product and have a hard 24-hour maximum runtime. Spot VMs replaced them as the current recommended option and have no fixed runtime limit, they run until reclaimed or until you shut them down, with pricing that can vary over time rather than being fixed at launch.

Teams switch to Spot VMs for batch jobs, CI runners, and stateless worker pools where a job can checkpoint or simply restart on a different instance. Neither is appropriate for a database primary or anything that can't tolerate being killed with roughly 30 seconds notice.

Concurrency controls how many requests a single container instance handles at once, up to 1000 per instance. A higher concurrency means fewer instances need to spin up under load, which is cheaper and reduces cold starts, but it only works if your workload is actually safe to run concurrently inside one process.

text
gcloud run deploy my-service 
 --image gcr.io/my-project/my-service 
 --concurrency=1 
 --cpu=2 --memory=2Gi

The default is wrong for CPU-bound work that blocks the event loop, image processing, PDF generation, anything that isn't just waiting on I/O. Setting concurrency to 1 for that kind of workload trades cost for correctness: each request gets its own container instance and can't be starved by a neighbor doing heavy work on the same instance.

Autopilot manages node provisioning, scaling, and most node-level configuration for you and bills per pod resource request rather than per node, which removes the job of right-sizing a node pool entirely. Standard gives you full control over node pools, machine types, and node-level configuration, including things Autopilot restricts like privileged containers, host networking, and certain DaemonSets.

You'd still pick Standard for workloads that genuinely need a DaemonSet with host access, a specific GPU or TPU configuration Autopilot doesn't yet support, or extremely cost-sensitive batch workloads where you can pack bin-pack better manually than Autopilot's per-pod billing works out to. For a typical stateless microservices platform, Autopilot is the lower-maintenance default and most teams starting fresh should pick it.

App Engine lets you deploy a new version without routing any traffic to it, then split traffic between versions by percentage or by an IP/cookie-based split for session affinity. Beyond canary deploys, teams use it for true A/B testing of a feature at the infrastructure layer, since the split is deterministic per user with cookie-based splitting, and for instant rollback: if the new version misbehaves, moving traffic back to the old version is a traffic-split change, not a redeploy.

text
gcloud app services set-traffic default 
 --splits=v2=0.1,v1=0.9 --split-by=cookie

Cloud SQL is managed MySQL, PostgreSQL, or SQL Server, a single primary with read replicas, and it's the right default for most applications that fit on one machine's worth of write throughput. AlloyDB is Google's PostgreSQL-compatible database built for higher throughput and analytical query performance on the same data, worth the switch when Cloud SQL Postgres's performance ceiling becomes the actual bottleneck, not before. Spanner is a globally distributed, horizontally scalable relational database with external consistency guarantees, the answer when you need multi-region strong consistency and horizontal write scaling beyond what a single primary can do, at a materially higher cost and operational complexity than either of the other two.

Firestore is the current product name, and it runs in one of two modes on the same underlying infrastructure. Native mode is the newer document-model API with real-time listeners and strong consistency by default, meant for mobile and web client SDKs. Datastore mode preserves the older Datastore API and eventual-consistency-by-default query semantics for backward compatibility with applications built before Firestore existed. A database, once created, is locked into whichever mode it started in, you can't switch it later, which is why some teams end up maintaining Datastore-mode projects years after everyone building something new defaults to Native mode.

Partitioning splits a table into segments, usually by date or by an integer range, and a query with a filter on the partitioning column skips scanning partitions that don't match, which directly reduces the bytes billed. Clustering sorts data within each partition (or within the whole table if unpartitioned) by up to four columns, so a query filtering or aggregating on clustered columns reads less data within the partitions it does scan, without a hard boundary the way partitions have.

sql
CREATE TABLE my_dataset.events
PARTITION BY DATE(event_timestamp)
CLUSTER BY user_id, event_type
AS SELECT * FROM my_dataset.raw_events;

Using both together is the normal pattern for a large time-series table: partition by day to prune most of the table immediately, then cluster by the column you filter or join on most often within a day's worth of data.

That's what Organization Policy constraints and IAM deny policies are for, and they're a genuinely different mechanism from allow bindings. Organization Policy constraints restrict what resources can be created or configured at all, disallowing external IPs on VMs, restricting which regions resources can be created in, regardless of what IAM role someone holds. IAM deny policies, added more recently, let you explicitly deny a permission to a principal even if some other allow binding would otherwise grant it, and deny always wins over allow.

text
gcloud resource-manager org-policies enable-enforce 
 compute.vmExternalIpAccess --project=my-project

Predefined roles are curated, versioned bundles of permissions that Google maintains and updates as new permissions get added to a service, roles/storage.objectViewer, roles/compute.instanceAdmin, that kind of thing. Custom roles let you assemble an exact list of permissions, which sounds like the more secure, least-privilege choice, but it comes with a real maintenance cost: when Google adds a new permission to a service that should logically belong in your custom role, it doesn't get added automatically the way it would to a predefined role, so custom roles quietly drift out of date.

Custom is worth it when a predefined role is genuinely too broad for a sensitive, narrow use case and you have a process for reviewing it periodically. It's usually the wrong choice as a default across an org, because most teams don't have that review process and end up with custom roles nobody remembers the reasoning behind two years later.

Data Access audit logs, specifically the Data Read and Data Write log types, record individual object-level access in Cloud Storage, but they're disabled by default for most services because of the volume and cost they generate at scale. You have to explicitly enable Data Access logs for Cloud Storage at the project or org level before the access you're trying to investigate happened, retroactive logging doesn't exist. Once enabled, the logs land in Cloud Logging and you'd query them with a filter on the resource name and time range, or export them to BigQuery for a proper audit query.

A GCP VPC is global by default, a single VPC can have subnets in every region, and resources in different regions on the same VPC communicate over Google's private backbone without crossing the public internet or needing peering between regions. AWS VPCs are region-scoped, so a multi-region AWS architecture needs VPC peering or a transit gateway to connect region-scoped VPCs together. In GCP, a multi-region deployment on a single VPC is the default topology, not something you build with an extra networking layer on top.

Shared VPC lets a host project own the VPC network and subnets, while one or more service projects attach to it and deploy resources into those shared subnets, with a central network team controlling the network topology and firewall rules while individual product teams keep their own project for billing, IAM, and resource management. VPC peering connects two separate, independently managed VPCs together, but each side still manages its own subnets, firewall rules, and routes independently, which doesn't give you the centralized control Shared VPC does.

Shared VPC is the standard pattern at any company with more than a couple of teams each needing their own project, since it avoids the alternative of either giving every team its own fully isolated network (which then needs peering everywhere) or putting every team's resources in one giant project (which breaks IAM and billing separation).

A global external load balancer uses Google's Anycast IP, a single IP address is announced from every Google edge location worldwide, and it routes each user to the closest healthy backend region automatically based on their location and backend health, all from one IP and one set of forwarding rules. A regional external load balancer is scoped to a single region and is simpler and cheaper when your entire user base and backend both live in one region anyway.

Global is the right call the moment you have backends in more than one region and want users routed to the nearest healthy one without manual DNS-based geo-routing, or when you need a single stable IP address regardless of which region is currently serving traffic during a regional failover.

Workload Identity lets a Kubernetes service account impersonate a GCP service account, so a pod gets GCP credentials scoped to exactly what it needs without a key file ever existing on disk inside the cluster. It replaced the older pattern of mounting a service account key as a Kubernetes Secret, which meant a downloaded, long-lived JSON key sitting in etcd and on every node that ran the pod, readable by anyone with access to that Secret.

text
gcloud iam service-accounts add-iam-policy-binding 
 gcp-sa@my-project.iam.gserviceaccount.com 
 --role roles/iam.workloadIdentityUser 
 --member "serviceAccount:my-project.svc.id.goog[my-namespace/my-ksa]"

The cluster autoscaler adds a node when there are pods that can't be scheduled anywhere in the cluster due to insufficient resources, and removes a node when every pod on it could be rescheduled elsewhere and the node has been underutilized for a sustained period. The horizontal pod autoscaler (HPA) operates one layer up, deciding how many replicas of a deployment should exist based on CPU, memory, or a custom metric, it has no idea whether the cluster actually has room for those replicas.

They can disagree in a real way: HPA can decide to scale a deployment up to handle load, but if the cluster autoscaler hasn't added capacity yet, those new pods sit in Pending state until a node becomes available, which is a real source of latency during a fast traffic spike that catches teams off guard the first time they see it.

At-least-once delivery means a message is guaranteed to be delivered one or more times, never zero, but duplicates are a normal, expected part of the contract, not an edge case. A message gets redelivered if the subscriber doesn't acknowledge it within the ack deadline, whether that's because processing genuinely failed or because the ack simply didn't make it back in time for reasons unrelated to whether the message was actually processed successfully.

Writing a correct subscriber means designing processing to be idempotent, using a message ID or a business-level key to detect and skip a duplicate, rather than assuming each message arrives exactly once. Pub/Sub does offer an exactly-once delivery mode for a subscription, but it trades some throughput and adds constraints, and most teams find it's simpler and more solid to just build idempotent handlers than to lean entirely on that guarantee.

A load job is free and batches data in from Cloud Storage or a similar source, but it's not instant, there's latency between the job running and the data being queryable, and it's meant for periodic bulk loads rather than continuous ingestion. Streaming inserts make rows queryable within seconds of being written, which is what you want for near-real-time dashboards, but they cost money per row inserted and historically had a quota on inserts per project per second that teams building high-volume pipelines had to design around.

The newer Storage Write API largely replaced the older streaming insert API for new projects, offering higher throughput and exactly-once semantics per stream at a lower cost than the legacy streaming inserts API, so most current guidance is to use that instead of the original tabledata.insertAll endpoint for new streaming pipelines.

An authorized view lets you share the result of a query, a filtered or joined subset of an underlying table, with users who have no direct access to the underlying table at all, only to the view. This matters when you want an analytics team to query a curated, row- or column-filtered version of a table containing sensitive data, without granting them read access to the raw table itself, which would let them bypass whatever filtering the view was meant to enforce.

sql
CREATE VIEW reporting_dataset.regional_sales AS
SELECT region, product, SUM(revenue) AS total_revenue
FROM raw_dataset.transactions
WHERE region = 'us-west'
GROUP BY region, product;

Writing directly to BigQuery from an application couples your application's write path to BigQuery's availability and quota limits, and it gives you no buffering if BigQuery has a transient issue or your write rate spikes past what a single ingestion path can handle cleanly. Putting Pub/Sub in front decouples the producer from the consumer entirely, the application just publishes a message and moves on, and Dataflow (or another subscriber) handles batching, retries, transformation, and backpressure on the read side without the original application ever needing to know or care.

The other real benefit is fan-out: the same Pub/Sub topic can feed BigQuery for analytics, a Cloud Function for real-time alerting, and a Cloud Storage archive simultaneously, three independent subscribers reading the same stream, which a direct write to one destination can't give you without the application itself writing to all three.

A budget alert notifies you, via email or a Pub/Sub message you can wire up to automation, when spending crosses a threshold percentage of a set budget amount. It does not stop any resource from running or block any further spending on its own, GCP has no built-in hard spending cap the way some people expect from the word "budget." Teams that want an actual enforcement mechanism have to build it themselves, commonly a Cloud Function triggered by the budget alert's Pub/Sub message that disables billing on the project or shuts down specific resources, and that automation is on the team to write and test, it isn't a checkbox GCP provides out of the box.

Sustained use discounts apply automatically, no commitment required, when a VM runs for a significant portion of the billing month, the discount scales up the longer it runs within that month. Committed use discounts require committing to a specific amount of vCPU and memory usage for a 1-year or 3-year term in exchange for a much larger discount than sustained use alone gives you, but you're on the hook for that spend whether you use the resources or not.

They aren't mutually exclusive in the way people sometimes assume, committed use discounts apply to usage up to the committed amount, and any additional usage beyond that on the same VM family can still pick up sustained use discounts, so a team with a stable baseline plus variable extra load can layer both.

A 429 means you've hit a quota or rate limit, and the wrong first move is immediately filing a quota increase request without checking whether the actual problem is a lack of retry-with-backoff logic in the calling code. Plenty of 429s happen because of a burst of near-simultaneous requests hitting a per-minute limit that would be perfectly fine spread out over a few seconds, and a quota increase just raises the ceiling on the same underlying bug rather than fixing it.

The right first step is checking the specific quota in the Quotas page to see which limit was actually hit and how close to it you were running before the spike, then adding exponential backoff with jitter to the client if the calling pattern is genuinely bursty, and only requesting a quota increase if the legitimate, well-behaved traffic still exceeds the current limit after that fix.

roles/bigquery.admin at the organization level lets that team create, modify, and delete every dataset and every job in every project under the org, not just query data, it includes the ability to change other users' access to datasets and to delete tables outright. Granting it broadly to avoid friction trades a real, hard-to-reverse blast radius for a convenience that a narrower structure solves just as well.

The better structure is a dedicated project (or a small number of them) that the data science team fully owns, with roles/bigquery.admin scoped to just that project, plus roles/bigquery.dataViewer granted at the specific dataset level in other teams' projects for the read-only data they actually need to query. That gives them full autonomy over their own workspace without a standing ability to delete a production dataset that belongs to another team entirely.

First, whether traffic that used to stay inside a single region is now crossing regions or zones, cross-region egress within GCP itself is billed and easy to introduce accidentally by adding a backend in a new region without checking where the majority of client traffic actually originates. Second, whether a service is serving large objects, backups, exports, media files, directly to the public internet from Cloud Storage or a VM instead of through a CDN, since CDN-cached responses are billed differently and far more cheaply than repeated direct egress for the same popular object. Third, whether a batch job or a new pipeline started shipping data to a destination outside GCP entirely, an external API, another cloud, a partner's endpoint, since egress to the public internet is priced meaningfully higher than intra-Google-Cloud traffic and a new integration is a common, easy-to-miss cause of a bill that jumped without anyone touching compute or storage configuration at all.

Hard questions

16

A sole-tenant node dedicates a physical server to a single customer's VMs, so no other Google Cloud customer's workloads ever run on that hardware. Regular Compute Engine VMs already run isolated by the hypervisor, sole tenancy isn't about security isolation in that sense, it's about licensing and compliance requirements that are tied to physical hardware rather than to a VM boundary.

The common driver is per-core or per-socket software licensing, certain Windows Server and SQL Server license terms require dedicated hardware to use Bring-Your-Own-License pricing instead of paying for a license bundled into the VM price. Some regulatory frameworks in specific industries also specify physical isolation requirements that a shared hypervisor tenancy model doesn't satisfy on paper, even though the actual security guarantees are similar.

Cloud Run's default networking egress goes to the public internet only, so reaching a VM with no external IP requires a Serverless VPC Access connector, a small managed set of VMs that bridges Cloud Run's environment into your VPC. Once the connector exists, you attach it to the Cloud Run service and set egress settings so traffic destined for internal IP ranges is routed through it rather than out to the internet.

text
gcloud compute networks vpc-access connectors create my-connector 
 --region=us-central1 --network=my-vpc --range=10.8.0.0/28

gcloud run deploy my-service 
 --vpc-connector=my-connector 
 --vpc-egress=private-ranges-only

The connector itself has a throughput ceiling based on its instance count and machine type, so under high load it can become the bottleneck rather than the VM you're calling, which is a detail that trips people up when they benchmark this path for the first time.

Spanner uses TrueTime, a Google-internal API backed by GPS and atomic clocks in every datacenter, that returns not a single timestamp but a bounded uncertainty interval for the current time. Spanner assigns commit timestamps using this interval and waits out the uncertainty window before acknowledging a commit, which guarantees that if transaction A commits before transaction B starts anywhere in the system, A's timestamp is provably earlier than B's, without requiring a single global sequencer that would become a bottleneck.

The practical cost of this is the commit wait, transactions hold slightly longer than they would in a system without this guarantee, because Spanner deliberately waits until it's certain the uncertainty window has passed. That's the trade Spanner makes for external consistency: a small, bounded latency tax in exchange for a guarantee most distributed databases don't offer at all.

Rotating a downloaded JSON service account key on a schedule reduces the blast radius of a leaked key but doesn't remove the underlying risk, the key is a static, long-lived credential that works from anywhere until it's revoked, and most teams find out a key leaked from a security scan or an incident, not from their rotation schedule catching it in time. Workload Identity Federation is the actual fix for workloads running outside GCP (CI pipelines, other clouds): it lets an external identity, a GitHub Actions OIDC token, an AWS IAM role, exchange a short-lived token for GCP credentials without ever creating or downloading a service account key at all.

For workloads running inside GCP, Compute Engine, GKE, Cloud Run, the equivalent fix is attaching a service account directly to the resource (or Workload Identity for GKE specifically) so the credential is scoped to that resource's runtime and is never a file that can be copied or leaked from a laptop or a CI log.

IAM controls who can call an API and what they can do, but a valid IAM permission plus a leaked credential or a compromised client can still exfiltrate data to a resource outside your organization, a personal Cloud Storage bucket in a different project, for example. A VPC Service Controls perimeter creates a boundary around a set of projects such that data can't cross it via supported APIs regardless of IAM permissions, so even a fully authorized principal with valid credentials can't copy data from inside the perimeter to a bucket or BigQuery dataset outside it.

It's the defense against data exfiltration specifically, not a replacement for IAM, teams run both together: IAM decides who can act, VPC Service Controls decides where the data is allowed to physically go.

Private Service Connect lets a consumer VPC reach a specific published service through an internal IP address in the consumer's own VPC, without the two VPCs being peered and without the producer's service ever having a route back into the consumer's network. This matters for SaaS-style architectures or internal platform teams serving many other teams, since VPC peering doesn't scale well past a handful of networks (peered networks can't have overlapping IP ranges, and peering isn't transitive), while Private Service Connect scales to many consumers with no such constraint.

GCP firewall rules evaluate lowest priority number first (0 is highest priority), but a common mistake is assuming rule order alone decides the outcome without checking that the rule's direction, target, and network tags actually match the traffic in question. A rule scoped to a specific network tag or service account only applies to instances carrying that exact tag or running as that service account, if the instance wasn't actually tagged the way you assumed, the rule silently never matches and traffic falls through to whatever rule does match, often the implied deny-all at the bottom.

The fastest way to debug this in practice is Firewall Rules Logging turned on for the suspect rule, which shows in Cloud Logging whether the rule was evaluated and matched at all for a given connection, rather than guessing from the rule list alone.

A PodDisruptionBudget (PDB) sets a floor on how many replicas of a deployment must stay available during a voluntary disruption, a node drain, a cluster upgrade, as opposed to an involuntary one like a node crashing. When GKE performs a node pool upgrade, it drains nodes one at a time (or in small batches depending on your surge upgrade settings), and the drain respects any PDB defined for pods running on that node, refusing to evict a pod if doing so would violate the budget.

yaml
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
 name: my-app-pdb
spec:
 minAvailable: 2
 selector:
  matchLabels:
   app: my-app

Without a PDB, a node pool upgrade can drain a node and take an entire deployment's replica count down to whatever's left running elsewhere at that moment, which is fine for a stateless service with plenty of headroom and genuinely dangerous for something like a small Kafka consumer group where losing more than one replica at once causes real disruption.

Node auto-provisioning on GKE Standard automatically creates and deletes entire node pools, not just nodes within a fixed pool, based on the resource requests and constraints (including things like specific GPU types or taints) of pending pods, which gets you most of Autopilot's hands-off node management while keeping the Standard tier's ability to run privileged workloads, custom DaemonSets, and specific machine shapes Autopilot restricts.

Teams pick this over pure Autopilot when they have a mix of workloads, some standard stateless services that would be fine on Autopilot, plus a handful with genuine Autopilot-incompatible requirements like host networking for a service mesh sidecar or a specific GPU family, and they'd rather manage one cluster with node auto-provisioning than split workloads across an Autopilot cluster and a separate Standard cluster.

Monitoring dashboards typically sample memory usage on an interval, every 30 or 60 seconds is common, and a short memory spike between samples, a burst during JSON parsing of a large payload, a garbage collection pause that lets allocations pile up right before a collection, can exceed the container's memory limit and trigger an immediate OOM kill from the kernel cgroup controller without ever showing up as a sustained line on a dashboard that only captures point-in-time samples.

The fix isn't just raising the limit blindly, it's checking the pod's actual restart count and OOM events via kubectl describe pod and correlating the timestamp against application logs to find what request or batch was running at that exact moment, then either fixing the underlying spike (streaming a large payload instead of buffering it whole) or setting the limit with enough headroom above the true peak, not just the average shown on a coarse graph.

A slot is a unit of BigQuery's compute capacity, CPU and memory bundled together for query execution. Under on-demand pricing, Google allocates slots dynamically per query from a shared pool with a generous ceiling, and you're billed per byte scanned regardless of how many slots your query used. Under a flat-rate reservation, you're paying for a fixed number of slots and every query, including concurrent ones from other teams sharing the reservation, draws from that same fixed pool.

A query that ran fast under on-demand can run slower under a flat-rate reservation if the reservation's slot count is smaller than what on-demand was effectively giving it, or if other concurrent queries in the same reservation are competing for the same fixed slots. This is the actual trade-off flat-rate reservations make: predictable cost in exchange for a capacity ceiling that on-demand doesn't have.

Dataflow autoscaling looks at the actual backlog of unprocessed data and the throughput each worker is achieving, not just CPU or memory utilization the way a generic autoscaler would, and it can scale a streaming pipeline both up and down continuously as the input rate changes. A batch job scaling down mid-run surprises people because Dataflow's autoscaler can reduce worker count once it estimates the remaining work can finish on fewer workers within the target time, even while the job is still actively running, rather than only scaling based on a fixed schedule or a simple queue-depth threshold.

Cold starts are the usual suspect here, a new function instance spinning up to handle a burst of concurrent requests takes measurably longer than a warm one, loading the runtime, initializing any global-scope code, establishing database connections, before it even starts the handler logic your logs are timing. If the timeout is set close to the typical warm execution time, a cold start alone can blow past it even though the actual handler logic, once running, finishes quickly and looks fine in the trace.

The fix depends on the function's traffic pattern: setting a minimum number of always-warm instances removes cold starts entirely for a service with steady baseline traffic, at the cost of paying for that idle capacity, while a bursty, infrequent workload is usually better served by widening the timeout and accepting occasional cold starts than by paying to keep instances warm around the clock.

The hardest part is almost never the compute or the load balancing, GCP's global load balancer and multi-region Cloud Run or GKE deployments handle that part reasonably well. It's the database: a traditional single-primary relational database can only accept writes in one region, so "active-active" for the write path specifically requires either Spanner, which is built for exactly this and gives you strong consistency across regions at a real cost premium, or accepting a weaker consistency model, like a Cloud SQL primary in one region with reads served from replicas elsewhere while writes still funnel back to the single primary region with added latency for users far from it.

Teams that skip this and just deploy stateless app tiers to multiple regions in front of a single-region database haven't actually built an active-active architecture, they've built an active-passive one with lower write latency in one region, which is a legitimate and much simpler design, it's just not the same thing the term implies, and being clear about that distinction out loud is usually the answer an interviewer is actually listening for.

Database Migration Service is built for exactly this: it sets up continuous replication from the source PostgreSQL instance to a Cloud SQL target, so the two stay in sync while the source keeps serving live traffic, and the actual cutover, the only real downtime window, is just the moment you stop writes to the source, let replication fully catch up, and repoint the application's connection string at Cloud SQL.

The parts that actually take planning aren't the data copy itself, it's confirming the source database's configuration is compatible (certain PostgreSQL extensions aren't supported on Cloud SQL), testing the cutover procedure including how the application handles a brief connection interruption, and having a clear rollback plan if something in the new environment behaves differently than expected once real traffic hits it, since that's the point where a migration that looked clean in staging tends to surface the actual surprises.

The Compute Engine default service account, if left with its default broad permissions, historically granted Editor-equivalent access to the whole project to any VM using it, which means a compromised VM running as the default service account could potentially read, modify, or delete almost anything else in the project, wildly out of proportion to what that VM's actual job requires. Security teams ban it specifically to force every VM to run under a purpose-built service account scoped to only the permissions that VM's workload actually needs.

The replacement pattern is a dedicated service account per workload (or per small group of related workloads), granted only the specific IAM roles that workload calls for, application default credentials still work exactly the same way from the VM's perspective, so nothing changes about how the application code authenticates, only what that identity is actually allowed to do once it's compromised.

How to prepare for a GCP interview in 2026

Skip another read-through of service names and pricing tiers. Build one small thing that forces you to reason about the resource hierarchy and IAM for real: a two-project setup with a Shared VPC, a service account scoped to exactly one BigQuery dataset instead of the whole project, and a VPC Service Controls perimeter around it. Break something on purpose, remove a permission and watch what actually fails, add an org policy constraint and see what stops working. That's the muscle interviewers are actually testing when they ask "how does IAM inheritance work," not whether you can recite the hierarchy from memory.

Across cloud and platform-engineer mock interviews run through LastRoundAI, the resource hierarchy and deny-policy question trips up more senior candidates than the Kubernetes autoscaling question does, even though Kubernetes gets more prep-guide attention by a wide margin. Our read is that most engineers learn Kubernetes hands-on because it breaks loudly and often, while IAM mostly works quietly in the background until the one day it doesn't, so people build less instinct for it. That's an observation from what we see in review sessions, not a number we'd defend to a decimal point.

One more thing worth knowing going into 2026: interviewers increasingly ask about Workload Identity Federation specifically, not as trivia, but because leaked service account keys are one of the most common real incidents security teams actually deal with, and an answer that jumps straight to "rotate the key faster" instead of "don't create a long-lived key at all" reads as dated to anyone who's dealt with an actual incident review.

Get the reps in before the real thing

Explaining IAM inheritance on a whiteboard is not the same as defending an architecture decision out loud once an interviewer changes one constraint and asks what breaks. LastRoundAI's mock interview mode runs live system-design and troubleshooting rounds with real-time follow-up questions in your browser, and the free plan includes 15 credits a month that reset monthly rather than piling up unused. Starter is $19/mo if a handful of sessions isn't enough runway.

Once your answers hold up under a follow-up, the slower part of the job hunt is usually just getting in front of enough cloud and platform roles that actually test GCP depth instead of treating "cloud experience" as interchangeable across providers. Auto-Apply queues tailored applications for your review, 10 a month on the free plan, up to 400 a month on the Ultimate plan, and nothing goes out until you approve it.

Questions about either product go to contact@lastroundai.com.

How this list was built

Worth being straight about where these questions come from, because plenty of pages in this category are not. The set was compiled from a research pass across official documentation, vendor release notes, published engineering writing and public discussion of hiring processes, then cross-checked against the current version of each technology so nothing here describes behaviour that has since changed.

What that means in practice: these are the questions the material supports as reasonable and current for this role, not a transcript of any one company's loop. We have not sat in on your interview and we are not going to claim we have. Treat the list as well-sourced preparation rather than a leaked question bank, and expect your panel to phrase things their own way.

If you spot something out of date, tell us at contact@lastroundai.com and we will fix it.

Frequently asked questions

What is the most common mistake in Google Cloud interviews?

Answering the question that was asked and stopping there. The strongest candidates add the trade-off or the failure mode without being prompted, which is what signals real use rather than revision.

How long does it take to prepare for a Google Cloud interview?

If you already work with Google Cloud day to day, a focused week on the areas you avoid in practice is usually enough. Coming in cold, expect three to four weeks. The gap is rarely knowledge; it is being able to explain something you normally just use.

What Google Cloud topics come up most often?

Interviewers concentrate on the parts that cause production incidents rather than the parts that are pleasant to learn. Expect the fundamentals to be assumed and the follow-up questions to sit one layer below what a tutorial covers.

Do I need hands-on Google Cloud experience to pass?

It shows quickly either way. Textbook answers hold up until the interviewer asks what you did when it broke, and that is usually the question that separates candidates. A small real project you can discuss honestly beats a longer list of familiarity claims.

Is Google Cloud still worth learning in 2026?

For interview purposes the question is really whether the teams you are targeting use it, which is worth checking against their actual job postings rather than general popularity rankings. Where it is in use it tends to be deeply embedded and slow to replace.

Leave a Reply

Your email address will not be published. Required fields are marked *