MLOps on Cloud — CI/CD for ML
GitHub Actions triggering retraining, model quality gates in CI, automated deployment to staging and production across Azure ML, SageMaker, and Vertex AI.
Software CI/CD is: push code → tests run → deploy if green. ML CI/CD is: push code or data → train model → quality gates run → deploy to staging → shadow test → promote to production. The same idea, four more steps.
Software engineers take CI/CD for granted. A pull request opens, unit tests run, integration tests run, and the change deploys automatically if everything passes. ML teams almost never have this. Retraining is manual — someone runs a notebook when they remember. Deployment is manual — someone SSH-es into a server and restarts a process. Quality gates are absent — a worse model can go to production because no one compared it to the incumbent. This is the gap that ML CI/CD closes.
The complete ML CI/CD pipeline has two orthogonal triggers. Code changes: a pull request modifying the training script or feature pipeline runs tests, trains a model on a small data sample, checks quality, and blocks the merge if it fails. Data changes or schedules: a weekly cron job or a drift alert triggers full retraining on production data, runs evaluation, compares to the champion model, and deploys if the challenger wins. Both flows use GitHub Actions — the same CI/CD tool your software team already uses.
A car manufacturer runs two quality checks. The design check happens when engineers submit a blueprint change — does the new design meet safety standards on paper? The production check happens on the assembly line — does the manufactured car meet standards in reality? ML CI/CD is the same: code-change tests (does the training script work correctly on a small sample?) and data-change tests (does the model trained on new production data beat the current production model?). Neither check alone is sufficient. Together they ensure nothing bad reaches customers.
The key shift in mindset: in ML, the model is not just code — it is code plus data plus hyperparameters. CI/CD must test all three dimensions simultaneously. A code change that looks fine in unit tests might produce a degraded model when combined with production data. The full pipeline test is the only reliable check.
Four-stage ML CI/CD pipeline — what runs, when, and what gates block progress
The pull request workflow — test ML code like software code
The retraining workflow — weekly cron, full cloud training, quality gate, deploy
Five scripts every ML CI pipeline needs — platform-agnostic patterns
Platform-agnostic CI/CD — the same workflow adapted for SageMaker and Vertex AI
The GitHub Actions workflow structure is identical across all three cloud platforms. Only the submit and compare scripts change. The abstraction pattern: write a thin adapter for each platform behind a common interface. The CI workflow calls the interface — it does not care which cloud is underneath. This lets you migrate between platforms without rewriting the entire CI pipeline.
Every common ML CI/CD mistake — explained and fixed
A real MLOps stack is assembled, not bought — managed services glued together with custom orchestration
Cloud vendors sell MLOps as a single coherent product — SageMaker, Vertex AI, Azure ML — each with a pipelines feature, a model registry, an endpoint service, and a monitoring dashboard. In practice almost no team runs the vendor's full stack end to end. A typical production setup at a mid-size company pulls training compute from one vendor service, orchestration from a separate tool the data team already runs, CI/CD from GitHub Actions because that is what the rest of engineering uses, and monitoring from Datadog or Grafana because the on-call rotation already lives there. MLOps in practice is integration work across tools that were never designed to talk to each other, held together by scripts like the ones in this module.
The reason this happens is organisational, not technical. The data engineering team standardised on Airflow years before the ML team existed, and migrating hundreds of existing DAGs to a vendor's pipeline format is not worth it just so three ML pipelines fit one ecosystem. The security team mandates a specific secrets manager and audit log format that the cloud vendor's native tooling does not speak natively. The on-call rotation already pages through PagerDuty. Every one of these constraints pulls the real stack away from "one platform does everything" and toward "one platform trains the model, everything else is glue code."
The practical skill this teaches is not "learn SageMaker" or "learn Vertex" — it is learning to write the adapter layer this module's cloud_adapter.py demonstrates, so the orchestration, CI, and monitoring choices your organisation already made can sit on top of whichever vendor training service you use underneath, and so a change in cloud vendor is a swapped adapter, not a rewritten pipeline.
Five things people get wrong about MLOps on the cloud
SageMaker, Vertex AI, and Azure ML each cover training, a registry, and deployment — the pieces vendors demo. What they rarely cover well is the orchestration that already runs your organisation's other data pipelines, the CI system the rest of engineering uses, the incident-response tooling on-call already lives in, and the specific audit or secrets requirements security already mandated. Real stacks end up using the vendor platform for the piece it is genuinely good at — usually training compute and the registry — and gluing everything else on top with the organisation's existing tools, exactly the pattern the CloudMLAdapter interface in this module is built to support.
Buying a platform gets you compute, a registry API, and a dashboard — none of which, by themselves, decide what quality gate a challenger model must clear, how much traffic shifts to it on day one, or who gets paged when the gate fails. Those decisions are organisational practice, encoded as the specific tolerance values, promotion rules, and rollback thresholds in this module's CI workflows. Two teams running the identical SageMaker setup can have completely different MLOps maturity depending on whether those practices exist, are enforced automatically, and are actually followed under deadline pressure.
Multi-cloud MLOps trades one risk for several others: every pipeline script now needs an adapter per platform (as cloud_adapter.py shows), every engineer needs at least working familiarity with two sets of IAM, networking, and quota systems, and every incident now has two places to check instead of one. It can be the right call when a single vendor's outage history, pricing, or GPU availability genuinely threatens the business — but that is a deliberate tradeoff against real added operational complexity, not a free upgrade to reliability.
The four-stage pipeline in this module gates on metrics it was told to check — MAE within tolerance, p99 latency, error rate. It cannot catch a challenger that is numerically better but has learned a new, unintended bias, or one trained on a data window that quietly excluded a whole customer segment. That is exactly why production-promote in this module's workflow example runs against a GitHub environment that can require manual approval — automating the mechanical checks frees humans to spend their attention on the judgment calls the pipeline cannot make, it does not remove the need for that judgment.
The retraining workflow in this module triggers on a schedule or a drift alert precisely because the data feeding the model changes continuously, and a deployment-only view of MLOps would have no mechanism to notice that. In practice, the data collection and cleaning pipelines from earlier modules are just as much a part of the MLOps surface as the CI/CD workflow — a schema change upstream or a silent drop in feature freshness breaks the model just as thoroughly as a bad deployment, and neither shows up if monitoring only watches the serving endpoint.
MLOps on cloud — 5 questions interviewers actually ask
I default to the managed service for anything that is genuinely hard infrastructure with no product-specific value in owning it — distributed training compute, GPU scheduling, managed endpoints for simple serving. I build in-house, or adapt an existing internal tool, for anything that encodes organisation-specific practice: promotion rules, quality gates, alerting thresholds, and the orchestration that ties training to the rest of the data platform. The dividing line is roughly: undifferentiated heavy lifting goes to the vendor, decisions that reflect how this specific team wants to operate stay in code the team owns.
The upside is real: one IAM model, one billing relationship, native integration between training, registry, and serving, and less adapter code to maintain. The cost is lock-in — migrating off SageMaker-specific pipeline definitions or Vertex-specific feature store APIs later is expensive, pricing negotiating leverage drops once switching is painful, and a regional outage on that vendor takes down the entire ML stack with no fallback. I would frame the decision around how much the organisation's other infrastructure is already committed to that cloud — going single-vendor on ML while everything else is multi-cloud is a different risk profile than going all-in on one vendor everywhere.
I would resist standing up a full four-stage pipeline on day one. Minimal viable looks like: training jobs submitted through whichever cloud SDK is cheapest for the team's compute needs, a single GitHub Actions workflow that runs unit tests and a smoke test on every PR, model versions tracked in something as simple as MLflow or even a naming convention in cloud storage, and one manual approval step before anything reaches production. The full automated four-stage pipeline in this module is worth building once retraining happens often enough that manual promotion is the actual bottleneck — not before.
The biggest risk is a challenger that passes every automated metric gate but is wrong in a way the gates were never told to check for — a subtle new bias, a data window that silently dropped a segment, a metric that looks better only because the evaluation set itself drifted. I mitigate this with gradual traffic promotion instead of an instant switch (10 percent, then 50, then 100, as this module's production-promote stage does), automatic rollback on any latency or error regression, and a required manual approval gate on the production environment so a human reviews the comparison numbers before the last step, even though every earlier step is fully automated.
I would look at what already runs the rest of the company's data workflows. If Airflow already orchestrates the data warehouse loads and feature pipelines, adding ML training as another set of Airflow DAGs keeps one orchestration system, one on-call rotation, and one place to see the whole data lineage — worth more than the tighter native integration a vendor's own orchestrator offers. I would lean toward the vendor's managed orchestrator only for a team with no existing orchestration investment, where the tighter coupling to that one cloud's training and registry APIs is a net simplification rather than one more system to learn.
The Cloud ML Platforms section and the entire AI/ML track are complete. Module 80 is your interview preparation — 50 complete ML answers.
You have covered 79 modules across ten sections: Math and Statistics, Python for ML, Classical ML, Deep Learning, NLP, Computer Vision, Generative AI, MLOps, and Cloud ML Platforms. Every concept connects to the next. Every module includes working code and real company examples. Module 80 is the capstone — 50 complete answers to the most common ML engineering interview questions asked at DoorDash, Stripe, Amazon, Brex, and every other major tech company.
The 50 most-asked ML engineering questions across DoorDash, Stripe, Amazon, Brex, and top tech companies — with complete, ready-to-deliver answers.
🎯 Key Takeaways
- ✓ML CI/CD has two orthogonal triggers: code changes (PR opened → unit tests + smoke test on 500 rows → block merge if any test fails) and data/schedule changes (weekly cron or drift alert → full cloud training → quality gate → staging deploy → production promote). Keep them separate — running full cloud training on every commit is wasteful and defeats the purpose of fast PR feedback.
- ✓Four-stage pipeline with a gate at every stage: unit tests + smoke test (no cloud cost, fast feedback), cloud training + champion comparison (MAE within 5% tolerance), staging integration + load tests (p99 < 500ms, error rate < 1%), gradual production promotion (10% → 50% → 100% with auto-rollback). A model cannot reach production unless it passes all four gates.
- ✓Store champion metrics explicitly when promoting a model — add val_mae as a tag on the registry entry. The compare_models.py script must retrieve the champion metric reliably. When no champion exists (first deployment), use a fallback of 999.0 to always promote. Log both metrics to Slack on every run so the team can visually sanity-check every comparison.
- ✓Platform-agnostic adapter pattern: write a CloudMLAdapter abstract class with submit_training_job, wait_for_job, register_model, and deploy_to_endpoint methods. Implement AzureMLAdapter and SageMakerAdapter (and VertexAdapter). Select via ML_PLATFORM environment variable. The GitHub Actions workflow calls the interface — never the platform SDK directly. Migrating clouds means swapping one env var.
- ✓GitHub Actions mechanics for ML: use outputs to pass data between jobs (job_name, challenger_mae, should_promote), needs: to enforce job order, if: conditions to skip stages when challengers fail, environment: with manual approval gates for production, and workflow_dispatch with inputs for manual retraining with custom parameters. Always set timeout-minutes on jobs that call cloud training APIs.
- ✓Four common CI/CD failures: job stalls and times out without failing (set explicit timeouts at both CI and cloud job level, add cleanup step to cancel the cloud job), comparison logic promotes a worse model (store and retrieve champion metrics explicitly, add sanity range checks), race condition runs production before staging (verify needs: chain with GitHub workflow visualiser), training runs on every commit and costs spike (separate code-change CI from data-change retraining triggers).
Discussion
0Have a better approach? Found something outdated? Share it — your knowledge helps everyone learning here.