Throughout this module we have deployed AlpinaShop's catalogue in four different ways: on virtual machines with a managed group, on App Engine with an app.yaml, in containers on GKE Autopilot, and we have mentioned Cloud Run and Cloud Functions as options studied later on. They all work. They all serve the same page. And they all have very different implications for cost, operational effort, deployment speed and the freedom you will have three years from now.
This lesson is the module's synthesis. It introduces no new services: it gives you the criteria for choosing among the ones you already know, with a complete comparison table, decision questions you can apply at work tomorrow, a transparent cost calculation over the same traffic scenario, the usual migration patterns and, at the end, AlpinaShop's definitive architecture, documented and reasoned, which will hold up the rest of the course.
Contents
- The continuum of abstraction
- What you gain and what you lose by going up a level
- Complete comparison table
- The six decision questions
- Comparing cost over the same scenario
- Migration patterns: lift-and-shift, replatform, refactor
- Hybrid architectures: hardly anyone picks just one
- AlpinaShop's architecture at the close of the module
- What is missing: the network
- The continuum of abstraction
Google Cloud's compute services are not a list of separate options: they form a continuum. At each step you hand control to the platform and get less operational work in return.
graph LR
A["Compute Engine<br/>VM<br/><i>you manage the OS</i>"]
B["GKE Standard<br/>Containers + nodes<br/><i>you manage the nodes</i>"]
C["GKE Autopilot<br/>Containers<br/><i>you manage the pods</i>"]
D["App Engine<br/>Code + app.yaml<br/><i>you manage the code</i>"]
E["Cloud Run<br/>Serverless container<br/><i>you manage the container</i>"]
F["Cloud Functions<br/>Function<br/><i>you manage a function</i>"]
A --> B --> C --> E --> F
C --> D --> E
style A fill:#e8eaf6,stroke:#3f51b5,color:#000
style B fill:#e3f2fd,stroke:#1976d2,color:#000
style C fill:#e0f7fa,stroke:#0097a7,color:#000
style D fill:#e8f5e9,stroke:#388e3c,color:#000
style E fill:#f1f8e9,stroke:#689f38,color:#000
style F fill:#fffde7,stroke:#fbc02d,color:#000
Read from left to right:
- Compute Engine. You supply a disk image and Google gives you a machine. Everything else — operating system, patches, runtime, web server, scaling, deployment — is yours.
- GKE Standard. You supply containers and decide the size and number of nodes. Kubernetes places the containers; you maintain the fleet of VMs.
- GKE Autopilot. You supply containers and declare how many resources they ask for. The nodes disappear from view.
- App Engine. You supply code and an
app.yaml. The containers disappear too. - Cloud Run. You supply a container and a minimal configuration. It scales to zero, is billed by usage and there is no visible infrastructure.
- Cloud Functions. You supply a function and a trigger. It is the smallest possible unit of deployment.
Notice that there are two routes to Cloud Run: from containers (GKE) and from code (App Engine). That convergence is no accident, and it explains why Cloud Run has become the meeting point of both worlds.
- What you gain and what you lose by going up a level
| Going up a level... | You gain | You lose |
|---|---|---|
| Operations | Less maintenance work | Less capacity for deep diagnosis |
| Deployment | Faster and with fewer steps | Less control over the process |
| Scaling | Automatic and more fine-grained | Less predictable behaviour |
| Cost | You pay only for what you use | Worse unit price at very high, constant usage |
| Security | Smaller attack surface, patches included | Less ability to apply your own controls |
| Start-up | (it gets worse) | Cold starts appear |
| State | — | Local disk, long processes, in-memory sessions |
| Portability | It depends: containers yes, proprietary formats no | Risk of vendor coupling |
Two nuances that avoid simplistic conclusions:
More abstraction is not always cheaper. A constant 24×7 workload comes out cheaper on Compute Engine with a committed use discount than on a serverless service billed per request. Serverless wins with intermittent or highly variable traffic, which is precisely AlpinaShop's case.
More abstraction is not always less portable. A container on Cloud Run is as portable as on GKE: the same image runs on both, on your laptop and on another cloud. What ties you down is not the level of abstraction, but the proprietary format: App Engine's app.yaml or the specific signatures of Cloud Functions.
- Complete comparison table
| Criterion | Compute Engine | GKE Standard | GKE Autopilot | App Engine standard | App Engine flexible | Cloud Run | Cloud Functions |
|---|---|---|---|---|---|---|---|
| Unit of deployment | Disk image / VM | Container | Container | Code + app.yaml |
Container | Container | Function |
| Scale to zero | No | No | No (minimum 1 pod) | Yes | No | Yes | Yes |
| Cold start | No (always on) | No | No | Yes (1–3 s) | No | Yes (100 ms–2 s) | Yes (100 ms–3 s) |
| Billing model | Per VM/hour | Per node + control plane | Per resources requested by the pods | Per instance hour | Per VM/hour | Per CPU-second, memory-second and requests | Per invocation, GB-s and GHz-s |
| Portability | Medium (VM image) | High | High | Low | Medium | High | Low |
| Max. execution time | Unlimited | Unlimited | Unlimited | 10 min (auto) / 24 h | 60 min | 60 min (HTTP) / 24 h (jobs) | 60 min |
| Operational effort | High | High | Medium | Low | Medium | Very low | Very low |
| OS control | Total | High (nodes) | Low | None | Medium | None (the image, yes) | None |
| State on local disk | Yes (persistent) | Yes (volumes) | Yes (volumes) | Only /tmp |
Yes (ephemeral) | Only /tmp (memory) |
Only /tmp (memory) |
| Concurrency per instance | Whatever you configure | Whatever you configure | Whatever you configure | Configurable | Configurable | Up to 1000 | 1 (by default) |
| GPU / special hardware | Yes | Yes | Limited | No | No | Yes (with restrictions) | No |
| Learning curve | Low | High | Medium | Low | Medium | Low | Very low |
| Best for | Lift-and-shift, total control, 24×7 workloads | Complex microservices, multicloud | Microservices with no platform team | Simple web in a supported language | Legacy that needs a container | APIs and web with variable traffic | Events, integrations, short tasks |
Two rows deserve an additional comment.
Concurrency per instance. It is the most misunderstood parameter and the one that moves the most money. Cloud Run can serve up to 1000 simultaneous requests on one instance; Cloud Functions serves one by default. For an application that spends its time waiting for the database, high concurrency means far fewer instances and a far smaller bill. For a CPU-bound application, raising it degrades latency for everyone.
Cold start. It exists whenever scaling to zero is possible. It is mitigated with minimum instances, but that removes precisely the advantage of scaling to zero. It is a trade-off, not a problem with a solution.
- The six decision questions
In practice, the choice is settled by answering six questions in order.
1. Do you need control of the operating system or special hardware? A specific kernel, drivers, GPUs, software licensed against hardware, corporate security agents, processes that must see the host. If the answer is yes → Compute Engine (or GKE Standard if you also want containers). If not, carry on.
2. Do you have containers, or are you willing to have them? If not and you do not want to learn now → App Engine standard or Compute Engine. If yes → carry on, everything else opens up. It is worth insisting: containerising is the investment with the best return in the whole module, because the same image works on Cloud Run, on GKE, on your laptop and on another cloud.
3. Do you need persistent local state or very long processes? In-memory sessions, local disk with data, processes lasting hours, servers with long-lived connections. If yes → Compute Engine or GKE. If not → carry on.
4. Is the traffic intermittent or highly variable? If traffic drops to almost zero at night or has seasonal peaks of ten to one → Cloud Run (it scales to zero, you pay for usage). If it is constant and high 24×7 → Compute Engine or GKE with committed use discounts work out better.
5. Is it a small unit of work triggered by an event? A file arriving in a bucket, a message in Pub/Sub, a webhook, a scheduled task → Cloud Functions. If it is a service with several routes and an API → Cloud Run.
6. Are you worried about vendor lock-in?
If it is a real criterion in your organization → containers (Cloud Run or GKE), which run anywhere. Avoid app.yaml and the proprietary signatures of functions.
And one cross-cutting rule that sums up the state of the art in 2026: if you have a web application or an API that can be containerised and none of the above constraints apply, Cloud Run is the default answer. It is the advice Google itself gives, and this course endorses it.
- Comparing cost over the same scenario
Comparing list prices is of no use at all; you have to compare the cost of a specific workload. We use AlpinaShop's:
Scenario. AlpinaShop's catalogue receives:
- 500,000 requests a month in a normal month (about 0.2 requests/second on average).
- A very uneven distribution: 80 % of the traffic between 09:00 and 23:00; practically nothing in the small hours.
- Campaign peaks: up to 20 requests/second for about 40 hours spread through the autumn.
- Each request consumes around 150 ms of CPU and 300 MiB of memory.
- The application needs ~0.25 vCPU and 512 MiB per instance.
| Option | Configuration | Indicative monthly cost | Comment |
|---|---|---|---|
| Compute Engine (MIG) | 2 × e2-medium 24×7 + load balancer |
~€50 (VMs) + ~€20 (load balancer) ≈ €70 | You pay 24 hours a day for capacity that goes unused in the small hours. With a 1-year committed use discount it would drop to ~€50 |
| GKE Autopilot | 3 pods of 0.25 vCPU / 512 MiB + control plane | ~€35 (pods) + ~€65 (control plane) ≈ €100 | The control plane dominates the cost at this scale. GKE pays off when there are many services sharing the cluster |
| App Engine standard | F2, min_instances: 1, max: 10 |
~€35–45 | Reasonable; the minimum of one warm instance is nearly the whole cost |
| App Engine standard | F2, min_instances: 0 |
~€5–10 | Very cheap, in exchange for cold starts on the first visit after each period of inactivity |
| Cloud Run | 0.5 vCPU / 512 MiB, concurrency 80, min-instances: 0 |
~€5–8 | It scales to zero overnight; peaks are absorbed by themselves. By far the cheapest option |
| Cloud Run | The same but with min-instances: 1 |
~€20–25 | Removes the cold start while keeping the cost low |
| Cloud Functions | Per invocation | ~€10–15 | Similar, but a poorer fit: a website with several routes is not a function |
Indicative figures for
europe-west1as of 2026, rounded, for the sole purpose of showing the order of magnitude and the way to reason. They do not include Cloud SQL, Cloud Storage, egress or CDN, which are common to all the options and which in this scenario exceed the compute itself. Always check the official Google Cloud calculator before taking a decision.
The conclusions to draw, which are worth more than the numbers:
- Scaling to zero matters when traffic is uneven. AlpinaShop has no traffic for eight hours a day; paying for capacity that is switched on during that time is pure waste.
- GKE's control plane is a significant fixed cost at small scale. Do not put it in place to deploy a single service; do put it in place when there are ten services sharing it, at which point that cost is diluted.
- Concurrency rules in Cloud Run. With a concurrency of 80, a peak of 20 requests per second is served by very few instances. If you lowered it to 1, you would need twenty times as many and the cost would multiply.
- Compute is usually not the biggest line item. In this scenario, Cloud SQL with high availability costs considerably more than any of the compute options. Optimising compute before the database and the egress is starting in the wrong place. The full cost optimisation discipline is in 07-05.
- Migration patterns: lift-and-shift, replatform, refactor
When a company moves an existing application to the cloud, there are three strategies, and most successful migrations go through them in order.
| Pattern | What it is | Effort | Benefit | Risk |
|---|---|---|---|---|
| Lift-and-shift (rehost) | Move it as it is onto VMs, without changing the application | Low | Low: you get off your own hardware and gain basic elasticity | Low |
| Replatform | Change infrastructure pieces without touching the logic: managed database, objects in Storage, containers | Medium | High: you eliminate most of the operational work | Medium |
| Refactor (rearchitecture) | Redesign the application: microservices, events, serverless | High | Very high in the long run | High |
Why the order matters. Trying to refactor and migrate at the same time is the classic recipe for the project that never ends: when something breaks, you do not know whether it was the architecture change or the platform change. Separating the variables reduces the risk drastically.
AlpinaShop's journey through this module has been exactly that:
- Lift-and-shift (02-01): the Flask catalogue onto a VM
alpinashop-web-1with a startup script, and then onto a managed group with autoscaling. The application did not change a line. - Replatform (02-02, 02-03, 02-06): the images moved off the local disk into the
alpinashop-catalogobucket; thetiendadatabase moved to the managed instancealpinashop-pedidoswith high availability and backups; the cart and the sessions moved to Firestore. The business logic is still the same; what changed is where each thing lives. - Refactor (in progress): containerising the application, which we already did for GKE in 02-05, and decoupling the asynchronous work with queues and events, which we started to see with Cloud Tasks in 02-04 and will complete with Pub/Sub in 04-04.
Why AlpinaShop starts on Compute Engine but is heading for containers. Starting on VMs was the right thing: it allowed the migration in a weekend without rewriting anything, with minimal risk and the possibility of going back. But the destination is containers, for three reasons we have already proved through the module:
- The container image is portable. The same one that runs on GKE runs on Cloud Run, on Dani's laptop and, if it were ever needed, on another provider.
- Deployment becomes trivial and reversible. Compared with versioned instance templates, startup scripts and disk images, a container is deployed and rolled back with one command.
- The investment compounds. Learning containers is useful across every service and across the whole industry; learning
app.yamlis useful in App Engine.
- Hybrid architectures: hardly anyone picks just one
The question "which compute service do I use?" is badly framed if it is asked once for the whole system. It is asked per workload, and it is normal to end up with several.
A complete, realistic architecture for AlpinaShop combines four:
graph TD
U((Customers)) --> LB[Global HTTPS load balancer<br/>+ Cloud CDN + Cloud Armor<br/><i>module 3</i>]
LB --> CR[Cloud Run<br/>alpinashop-web<br/><i>catalogue and checkout</i>]
LB --> ST[Cloud Storage<br/>alpinashop-catalogo<br/><i>images</i>]
CR --> SQL[(Cloud SQL<br/>alpinashop-pedidos)]
CR --> FS[(Firestore<br/>carts and sessions)]
CR --> PS[Pub/Sub<br/>pedidos-nuevos]
PS --> CF[Cloud Functions<br/>confirmation email]
PS --> CF2[Cloud Functions<br/>image thumbnails]
SCH[Cloud Scheduler] --> JOB[Cloud Run Job<br/>nightly export]
JOB --> BQ[(BigQuery<br/>alpinashop_analitica)]
GPU[Compute Engine Spot<br/>image reprocessing] -.-> ST
The allocation and the reason:
| Workload | Service | Reason |
|---|---|---|
| Web catalogue and checkout | Cloud Run | Variable traffic, scales to zero, portable container |
| Sending emails, generating thumbnails | Cloud Functions | Triggered by events, short execution, minimal code |
| Nightly export to BigQuery | Cloud Run Jobs + Cloud Scheduler | A batch task that finishes; it reuses the same image |
| Bulk reprocessing of the 60,000 images | Compute Engine Spot | CPU intensive, tolerant of interruption, minimal cost |
| Future internal services | GKE Autopilot | Only if they become numerous and sharing a cluster pays off |
This mixture is not indecision: it is using the right tool for each job. The cost of the variety is having to know several services; the benefit is not forcing any workload into a model that does not fit it.
- AlpinaShop's architecture at the close of the module
This is the documented decision that closes module 2 and that will serve as the basis for the rest of the course.
Current state (what has been built in this module):
| Component | Resource | State |
|---|---|---|
| Hierarchy | Organization alpinashop.example, folders produccion/desarrollo/compartido |
Up and running (01-04) |
| Projects | alpinashop-prod, alpinashop-dev, alpinashop-datos, alpinashop-cicd |
Up and running (01-04) |
| Region | europe-west1, zone europe-west1-b |
Decided (01-05) |
| Current compute | VM alpinashop-web-1 + regional MIG with autoscaling 2–10 |
Working (02-01) |
| Images | Bucket alpinashop-catalogo, regional, uniform access, lifecycle |
Migrated (02-02) |
| Database | Cloud SQL alpinashop-pedidos, PostgreSQL 16, regional HA, PITR, read replica |
Migrated (02-03) |
| Cart and sessions | Firestore Native, collections carritos and sesiones with TTL |
Designed (02-06) |
| Container | Image in Artifact Registry europe-west1-docker.pkg.dev/alpinashop-prod/alpinashop/catalogo |
Built (02-05) |
| Cluster | GKE Autopilot alpinashop-cluster |
Created and validated (02-05) |
Target architecture decision:
-
The web catalogue (
alpinashop-web) will go to Cloud Run. Intermittent traffic with seasonal peaks, a container already built, scaling to zero, a much lower cost than the alternatives and no vendor coupling. It will be configured withmin-instances: 1in production to avoid cold starts on the first visit, and high concurrency because the application spends most of its time waiting for the database. Cloud Run is studied in 07-02. -
The
alpinashop-clustercluster is kept as a platform for the internal services that come along (administration panel, ERP integration, stock synchronisation processes). Once there are three or more, the control plane cost will be amortised. In the meantime, it stays switched off or reduced to the minimum. -
Compute Engine is kept for batch work with Spot VMs: image reprocessing, load testing, one-off CPU-intensive tasks.
-
App Engine is rejected, on reasoned grounds: it works well, but its own format is not portable and the investment does not compound. It is known, it has been tried and it is set aside.
-
Cloud Functions is reserved for event-driven work: order confirmation emails, thumbnail generation when an image is uploaded to the bucket, payment gateway webhooks (06-03).
-
The data stays as decided in 02-06: Cloud SQL for products, orders and customers; Firestore for the cart and sessions; Cloud Storage for images; Memorystore as the front page cache; Pub/Sub and BigQuery for the telemetry, with Bigtable rejected for now.
Migration route agreed with Marta, Dani and Lucía:
| Phase | Action | Course module |
|---|---|---|
| Done | Lift-and-shift to VMs, images to Storage, database to Cloud SQL | Module 2 |
| Next | Private network, HTTPS load balancer, CDN, IAM and secrets | Module 3 |
| After that | Analytics in BigQuery, events with Pub/Sub | Module 4 |
| After that | CI/CD with Cloud Build, monitoring, Terraform | Module 6 |
| Destination | Catalogue on Cloud Run, internal services on GKE, SLOs defined | Module 7 |
- What is missing: the network
Look back over what has been built in this module with a critical eye and you will find a serious problem.
The VM alpinashop-web-1 has a public IP and port 80 open to the whole internet. So do the managed group's instances. The GKE LoadBalancer Service exposed a direct public IP, with no HTTPS. The Cloud SQL instance, if it was created with a public IP and authorised networks, is reachable from outside. The buckets are well protected, but signed URLs travel over HTTP if someone uses them badly. There is no domain name of our own, no TLS certificate, no protection against denial of service attacks or SQL injection, and no network separation between what should be public (the catalogue) and what should never be (the database).
Put bluntly: we have built a working shop and left it with the door open and no sign above it. Everything in this module was fine for learning and for testing; none of it is publishable as it stands.
That is exactly what module 3 solves.
Common Mistakes and Tips
- Choosing the service before understanding the workload. The traffic pattern, the duration of the requests and the need for state determine the answer; personal taste does not.
- Choosing Kubernetes by default. It is an excellent tool for many services and for teams with platform capacity. For one service and one person, it is pure overhead.
- Comparing list prices instead of the cost of the workload. The price per vCPU-hour says nothing if you do not know how many hours you are going to need.
- Forgetting the cost of GKE's control plane when comparing with serverless alternatives at small scale.
- Leaving Cloud Run's concurrency at 1 "to be safe". It multiplies the number of instances and the cost.
- Refactoring and migrating at the same time. When something fails, you will not know which change caused it.
- Staying on lift-and-shift forever. It is a legitimate starting point and a bad destination: you are still maintaining servers.
- Accepting vendor coupling without deciding on it. If you are going to take it on, let it be a conscious and recorded decision, not an accident.
- Tip: containerise even if you are not going to use Kubernetes. It is what opens up the most options for the least effort.
- Tip: decide per workload, not per system. An architecture with Cloud Run, functions and Spot VMs is not incoherent: it is appropriate.
- Tip: document and date every architecture decision, with the alternatives rejected and the reason. That is what lets you revisit it sensibly a year later.
- Tip: measure before optimising. The spend is almost always where you do not expect it, and rarely in the compute.
Exercises
Exercise 1: choosing a service for five workloads
For each AlpinaShop workload, choose the compute service, state a reasonable alternative and justify the decision by applying the six questions from section 4:
- A stock REST API that suppliers query, with irregular traffic and very little at night.
- A process that, every time an image is uploaded to the bucket, generates the thumbnail and the web version.
- A synchronisation server with the on-premises ERP that holds a permanent connection and keeps state on disk.
- The internal administration panel, used by 8 people during office hours.
- A one-off reprocessing of the 60,000 images that takes 3 hours and can be retried.
Exercise 2: reasoned cost comparison
An internal AlpinaShop service receives 100,000 requests a month, each one taking 200 ms of CPU, it needs 0.5 vCPU and 1 GiB of memory, and its traffic is concentrated in office hours (about 9 hours a day, 22 days a month).
- Estimate the cost on Compute Engine with a VM switched on 24×7.
- Estimate the cost if it is switched off outside working hours.
- Estimate the cost on Cloud Run with scaling to zero.
- State from what traffic volume Compute Engine would start to be competitive.
- List which costs you have left out of the calculation and why they could reverse the conclusion.
Exercise 3: documenting an architecture decision
Write the architecture decision document for AlpinaShop's catalogue, with this structure:
- Context: starting situation and constraints.
- Options considered: at least four, with one advantage and one drawback each.
- Decision: what is chosen and with what specific configuration.
- Consequences: what improves, what gets worse and what is left outstanding.
- Review criteria: what would have to happen for it to be reconsidered.
Solutions
Solution 1
| Workload | Choice | Alternative | Justification |
|---|---|---|---|
| 1. Stock API | Cloud Run | App Engine standard | Q1 no (no OS needs), Q2 yes (containerisable), Q3 no (stateless), Q4 yes (irregular traffic, almost none at night), Q5 no (it is an API with routes, not an event), Q6 yes (portable container). Scaling to zero and billing by usage |
| 2. Thumbnails on image upload | Cloud Functions | Cloud Run with an Eventarc trigger | Q5 yes: a small unit of work triggered by a Cloud Storage event. Minimal code, no server to maintain. If the processing were heavy or needed system libraries, Cloud Run with your own container |
| 3. ERP synchronisation | Compute Engine | GKE Standard with a persistent volume | Q3 yes: a permanent connection and state on local disk. Serverless services do not fit: they recycle instances and only offer /tmp in memory |
| 4. Internal panel | Cloud Run with min-instances: 0 |
App Engine standard with basic_scaling |
Low, concentrated traffic; eight people tolerate a one-second cold start perfectly well. Practically zero cost outside working hours |
| 5. Reprocessing 60,000 images | Compute Engine Spot | Cloud Run Jobs with parallelism | Q1 no, but Q4 and the profile of the task rule: CPU intensive, tolerant of interruption, long-running. Spot cuts the cost by between 60 and 90 % and the result goes to Cloud Storage, so losing the instance only means retrying |
Solution 2
Scenario data: - 100,000 requests/month x 0.2 s of CPU = 20,000 s of CPU a month - It needs 0.5 vCPU and 1 GiB - Activity: 9 h/day x 22 days = 198 h/month (out of 730 h in the month)
1. Compute Engine 24×7. An e2-small (2 shared vCPU, 2 GiB) comes to around €13–15/month, plus about €2 for the 20 GB balanced disk: ≈ €16/month. You pay for the machine for all 730 hours of the month, even though it is only used for 198.
2. Compute Engine switched off outside working hours. With 198 hours on out of 730, the compute cost drops to 27 %: around €4. The disk is still paid for in full (≈€2), because disks bill whether the machines are on or off. Total: ≈ €6/month, plus the work of automating the switching on and off with Cloud Scheduler and a function.
3. Cloud Run with scaling to zero. Approximate billing:
At the indicative prices for europe-west1, all of that comes to somewhere around €1–2/month, and a good part of it may fall inside Cloud Run's monthly free tier. It is between 3 and 10 times cheaper than the previous options, with no automation work at all.
4. When does Compute Engine start to pay off? When the machine is busy in a sustained way. The break-even point arrives roughly when the CPU usage billed in Cloud Run gets close to having one vCPU continuously occupied: on the order of several million requests a month with this profile, or any workload that keeps the CPU working 24 hours a day. Adding a one- or three-year committed use discount lowers that threshold considerably. The mental rule is clear: serverless wins with intermittent traffic; VMs win with constant, high load.
5. Costs left out, and why they can change the conclusion:
- Load balancer and static IP (~€18–20/month on Compute Engine). Cloud Run includes a managed HTTPS endpoint, which widens its advantage still further.
- Egress and CDN, common to all the options, but which in a shop with images exceed the compute.
- Cloud SQL, which in this scenario costs more than any of the compute options compared.
- People's time. Maintaining a VM (patches, monitoring, automating the switching on) is hours of Marta's time. Valued at market rates, the €10/month saving from option 2 disappears with the first hour of work each month.
- Committed use and sustained use discounts, which apply only to Compute Engine and GKE and can cut their cost by between 20 and 55 %.
This last point is the most important and the most frequently forgotten: the cost of an architecture is not just its bill.
Solution 3
DA-001 — Compute service for AlpinaShop's web catalogue Date: 2026-08-05 · Authors: Marta (infrastructure), Dani (backend) · Status: accepted
1. Context. The web catalogue is a Python Flask application with PostgreSQL, currently deployed on a Compute Engine managed instance group following the lift-and-shift. The traffic is intermittent: practically nil in the small hours, with peaks of up to 20 requests per second during the autumn campaigns. The infrastructure team is one person. The application is already containerised and its image published in Artifact Registry. It requires no state on local disk and no operating system access. Constraints: minimise operational work, avoid vendor coupling and contain the cost outside the campaign.
2. Options considered.
| Option | Advantage | Drawback |
|---|---|---|
| Compute Engine + MIG (the current situation) | Total control; it already works | 24×7 cost; maintenance of the OS, templates and startup scripts falling on a single person |
| App Engine standard | Very simple deployment; scales to zero | Proprietary, non-portable format; limited runtimes; the investment does not compound |
| GKE Autopilot | Portable containers; a base for future services | Fixed control plane cost; unjustified complexity for a single service |
| Cloud Run | Scales to zero; billing by usage; portable container; managed HTTPS; minimal operational effort | Cold starts if min-instances: 0; no local state; maximum 60 minutes per request |
3. Decision. Deploy alpinashop-web on Cloud Run, in europe-west1, with the image europe-west1-docker.pkg.dev/alpinashop-prod/alpinashop/catalogo, tagged with the commit hash. Configuration: min-instances: 1 and max-instances: 50 in production; min-instances: 0 in development; concurrency 80; 1 vCPU and 512 MiB per instance; connection to Cloud SQL through the connector; credentials resolved by the attached service account; secrets in Secret Manager. The alpinashop-cluster cluster is kept for future internal services. Compute Engine is kept solely for batch work with Spot VMs.
4. Consequences. Improves: operating system maintenance, instance templates and startup scripts all disappear; the compute cost drops by roughly an order of magnitude outside the campaign; deployments and rollbacks become immediate with traffic splitting between revisions; managed HTTPS is obtained with no configuration. Gets worse: control of the operating system and the ability to diagnose at a low level are lost; the possibility of cold starts appears in development; tasks longer than 60 minutes have to run outside Cloud Run. Outstanding: global HTTPS load balancer with our own domain, Cloud CDN, Cloud Armor and a private network towards Cloud SQL (module 3); automated deployment pipeline (module 6).
5. Review criteria. This decision will be reconsidered if: the number of internal services exceeds three, in which case GKE Autopilot amortises its control plane and could absorb the catalogue too; the traffic becomes constant and high 24×7, a scenario in which Compute Engine or GKE with committed use discounts would be cheaper; a requirement appears for local state or processes longer than 60 minutes; or the cold start affects business metrics despite min-instances: 1. Scheduled review: August 2027, or sooner if any of the above criteria are met.
Conclusion
We close module 2 with judgement, which is what distinguishes knowing a platform from knowing how to use it. You have seen that Google Cloud's compute services form a continuum of abstraction — from the virtual machine to the function — and that at each step you hand over control in exchange for operational work. You know what is gained and what is lost by going up a level, and also the two nuances that avoid easy conclusions: more abstraction is not always cheaper, because a constant 24×7 workload works out better on VMs with a use commitment, and more abstraction is not always less portable, because what ties you down is not the level but the proprietary format.
You have a complete comparison table of seven options with criteria that can be measured — unit of deployment, scaling to zero, cold start, billing, portability, maximum time, operational effort, concurrency — and six decision questions you can apply tomorrow to any workload: operating system control, containers, state and duration, traffic pattern, event triggering and vendor lock-in. You have done a transparent cost calculation over AlpinaShop's real scenario and drawn the lessons that matter more than the numbers: scaling to zero rules when traffic is uneven, GKE's control plane is a significant fixed cost at small scale, concurrency governs the cost on Cloud Run, and compute is rarely the biggest line item on the bill. You have gone through the three migration patterns and understood why separating the migration from the redesign reduces risk, and why AlpinaShop started on Compute Engine but is heading for containers. And you have seen that the right question is not asked once for the whole system, but once per workload: the target architecture combines Cloud Run, Cloud Functions, Cloud Run Jobs, Spot VMs and a GKE cluster held in reserve.
Looking back over the whole module: we created virtual machines with templates, regional managed groups, autoscaling and auto-healing; we moved the 60 GB of images into the alpinashop-catalogo bucket with storage classes, lifecycle, versioning and signed URLs; we migrated the tienda database to alpinashop-pedidos with regional high availability, PITR and a read replica; we tried App Engine with its app.yaml, its traffic splitting and its cron, and rejected it with arguments; we containerised the application, published it in Artifact Registry and deployed it on alpinashop-cluster on GKE Autopilot with an HPA, probes, secrets and interruption-free updates; we distributed the data across Cloud SQL, Firestore, Memorystore, Cloud Storage and BigQuery with a decision tree; and we have finished by documenting and dating the complete architecture. AlpinaShop's migration is no longer a plan: it is infrastructure that works.
And it ends with an obvious problem. Everything we have built is exposed: the VM has port 80 open to the internet, the GKE Service published an IP with no HTTPS, the database is reachable from outside, there is no domain of our own and no certificate, there is no protection against attacks and there is no network separation between what should be public and what should never be. In module 3, Networking and security, we fix it at the root: we will design AlpinaShop's VPC network with subnets and firewall rules, put a global HTTPS load balancer in front of the catalogue, speed up the images with Cloud CDN, distribute permissions with IAM applying least privilege to Marta, Dani and Lucía, protect the shop with Cloud Armor, keep the credentials in Secret Manager with encryption managed by Cloud KMS, and publish alpinashop.example with Cloud DNS and managed TLS certificates. What works today will also become publishable.
Google Cloud Platform (GCP) Course
Module 1: Introduction to Google Cloud Platform
- What is Google Cloud Platform?
- Setting Up Your GCP Account
- A Tour of the GCP Console
- Projects, Resource Hierarchy and Billing
- Regions, Zones and the Shared Responsibility Model
- Cloud Shell and the gcloud CLI
Module 2: Core GCP Services
- Compute Engine: Virtual Machines on Google Cloud
- Cloud Storage: Object Storage
- Cloud SQL: Managed Relational Databases
- App Engine: Platform as a Service
- Google Kubernetes Engine (GKE)
- NoSQL Databases: Firestore, Bigtable and Spanner
- How to Choose the Right Compute Service
Module 3: Networking and Security
- VPC Networks
- Cloud Load Balancing
- Cloud CDN
- Identity and Access Management (IAM)
- Cloud Armor
- Secrets and Encryption: Secret Manager and Cloud KMS
- Cloud DNS, TLS Certificates and Publishing Services Securely
Module 4: Data and Analytics
- BigQuery: The Analytical Data Warehouse
- Cloud Dataflow: Batch and Streaming Data Processing
- Cloud Dataproc: Managed Spark and Hadoop
- Cloud Pub/Sub: Asynchronous Messaging
- Cloud Data Fusion: Code-Free Data Integration
- Orchestrating Pipelines with Cloud Composer and Workflows
- Data Governance and Dashboards with Dataplex and Looker Studio
Module 5: Machine Learning and AI
- Vertex AI: The Machine Learning Platform on GCP
- AutoML: Custom Models Without Writing Code
- TensorFlow on GCP: Training and Serving Models
- Natural Language API
- Vision API
- Generative AI on Vertex AI: Gemini Models and Embeddings
- MLOps: From Model to Product with Vertex AI Pipelines
Module 6: DevOps and Monitoring
- Cloud Build: Continuous Integration on GCP
- Cloud Source Repositories and Source Code Management
- Cloud Functions: Serverless Functions
- Cloud Monitoring (formerly Stackdriver): Metrics, Dashboards and Alerts
- Cloud Deployment Manager and Native Infrastructure as Code
- Cloud Logging and Cloud Trace: Logs, Traces and Diagnostics
- Terraform on GCP: Infrastructure as Code in Practice
Module 7: Advanced GCP Topics
- Hybrid and Multicloud with Anthos
- Serverless Computing with Cloud Run
- Advanced Networking: Shared VPC, Peering and Hybrid Connectivity
- Security Best Practices
- Cost Management and Optimization
- Reliability: SLOs, High Availability and Disaster Recovery
- Governance at Scale: Organization, Policies and Auditing
