Home › Guides › MLOps projects
Tech Explained · 2026MLOps Projects in 2026: 6 Portfolio Builds With Real Pipelines, Registries and Drift Alerts
MLOps projects are portfolio builds that prove you can run a model in production rather than only train one: experiment tracking, a model registry, CI/CD, containerised serving, drift monitoring and gated retraining. The 6 builds below run on free tiers, take 8 to 20 hours each, and answer one specific interview question.
- Training is the small part. Fitting the model is roughly 8% of the hours; plumbing eats the rest.
- The free tiers are narrow. GitHub's Free plan: 2,000 Linux Actions minutes a month on private repos, unlimited on public.
- Hugging Face changed the rules. Per the Hub's docs, a Gradio or Docker Space now needs a paid plan.
- Drift monitoring is the differentiator. Almost nobody builds it, which is why interviewers remember it.
- Use aliases, not stages. MLflow deprecated registry stages from 2.9; the old call dates your project.
Your notebook gets 0.91 AUC. The number goes into a slide, the model goes to a colleague, and six weeks later somebody asks why the predictions look odd and nobody can say which dataset produced that 0.91. Closing that gap is the job.
What MLOps Projects Actually Need to Prove
Nobody screening for an operations role cares whether you know gradient boosting. They want three things: a result you can reproduce, a deployment you can reverse, and evidence you would spot a break first.
Take Meera, a 2021-batch Python developer in Pune who writes reporting scripts for a mid-size insurer and has 30 spare hours a month. She has trained plenty of models, and never stayed responsible for one.
Three numbers worth knowing before you start
Each changes a decision below, not just the framing.
GitHub and Hugging Face figures from their published plan and Spaces docs; hiring figure from Naukri JobSpeak. Checked 7 November 2026.
The honest caveat
These projects will not, by themselves, get a fresher hired as an MLOps engineer. Most Indian MLOps job descriptions ask for three or more years of production experience, and no portfolio substitutes for having been paged at 2am. What they reliably do is move you sideways: reporting into data engineering, backend into platform work.
The Reference Architecture All 6 Projects Share
The loop every MLOps project is a slice of
The retrain path along the bottom is the one most portfolios never build.
Component names are the tools used in each build below, checked 7 November 2026.
Copy one decision: the retrain arrow passes through a human. Automatic retraining sounds impressive and is a trap, for a reason below. Promotion and rollback on a live Azure stack is the core of 360DT's MLOps Engineer course.
6 MLOps Project Ideas, With Stack, Dataset and the Interview Question Each One Answers
Pick by the gap in your CV. Never shipped anything, build 1 and 3. Already deploying at work, go straight to 4 and 6, which read as operations experience rather than tutorial completion.
Six builds, scoped
Each is a slice of the loop above, defending one claim on your CV.
Tracked training with a promotion gate
Log three runs, register the best, then attach a champion alias only if it beats the incumbent. The gate is the project, not the model.
CI that blocks a bad model
Retrain on a fixed slice per pull request, compare against a committed baseline, fail on regression. Reviewers see a red X caused by a model.
CI/CDContainerised inference, pinned by alias
A FastAPI service loading models:/churn@champion at startup and printing the resolved version in /healthz. Prove rollback: move the alias back, restart.
Drift monitoring with a real alert
Log predictions with their features, compare the last hour against the training distribution on a schedule, alert past a threshold. Poison a feature to show it firing.
MonitoringReproducible feature pipeline
Date-partitioned Parquet plus a manifest of row count, column hash and source commit. Re-run training on last Tuesday's partition, get identical features.
Data lineageGated automatic retraining
Wire build 4's alert to a training run that registers a candidate and promotes nothing. A human approves the alias move. Explaining why beats automating it.
GovernanceScoping reflects the stacks and free tiers verified on 7 November 2026.
| Build | Stack | Dataset | Hours | The question it answers |
|---|---|---|---|---|
| 1. Tracked training + gate | MLflow, scikit-learn, SQLite | UCI Bank Marketing | 8 to 10 | "When is a version safe to promote?" |
| 2. CI that blocks a bad model | GitHub Actions, pytest, baseline JSON | Build 1's data, one slice | 10 to 12 | "What stops a worse model shipping?" |
| 3. Containerised inference | FastAPI, Docker, MLflow client | None; serves build 1's model | 10 to 14 | "Walk me through a rollback." |
| 4. Drift monitoring + alert | Evidently or SciPy, cron, webhook | Build 3's prediction log | 14 to 18 | "How would you know it had gone stale?" |
| 5. Reproducible features | DuckDB, Parquet, JSON manifest | NYC TLC trip data | 12 to 16 | "Reproduce last month's number for me." |
| 6. Gated retraining | Builds 1, 2 and 4 wired together | Nothing new | 16 to 20 | "Why would you not retrain automatically?" |
On tooling I will commit: MLflow, not a hosted tracker. Not because it wins on features, but because a reviewer can clone your repo, run mlflow ui and see your runs without an account. You give up collaboration features that do not matter when the team is one person. The releases page lists MLflow 3.18.0, published 4 November 2026, so pin the minor version.
Also read: if you have nothing trained yet, start with Machine Learning Projects for Beginners 2026 and come back with a model in hand.
Project 1 Walkthrough: From a CSV to a Promoted Model Version
The full build, with the output at each step. Meera does this on a Saturday afternoon, locally, no cloud account.
Step 1: a tracking server you can point someone at
python -m venv .venv && source .venv/bin/activate
pip install "mlflow==3.18.0" scikit-learn pandas pyarrow
# The registry needs a database backend. The default file
# store will refuse to register a model.
mlflow server \
--backend-store-uri sqlite:///mlflow.db \
--default-artifact-root ./mlruns \
--host 127.0.0.1 --port 5000
Step 2: log three runs, register one
Open http://127.0.0.1:5000 and you should see an empty experiment list. The point of the loop below is not the sweep: each run records its parameters, its metric and a hash of the input, so the registered version traces back to data.
import hashlib, json, mlflow, pandas as pd
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import roc_auc_score
mlflow.set_tracking_uri("http://127.0.0.1:5000")
mlflow.set_experiment("churn")
df = pd.read_csv("bank.csv", sep=";")
y = (df.pop("y") == "yes").astype(int)
X = pd.get_dummies(df, drop_first=True)
data_hash = hashlib.sha256(pd.util.hash_pandas_object(X).values).hexdigest()[:12]
Xtr, Xte, ytr, yte = train_test_split(X, y, test_size=0.2,
stratify=y, random_state=42)
best = (None, -1.0)
for depth in (2, 3, 5):
with mlflow.start_run(run_name=f"gb-depth-{depth}") as run:
model = GradientBoostingClassifier(max_depth=depth, random_state=42)
model.fit(Xtr, ytr)
auc = roc_auc_score(yte, model.predict_proba(Xte)[:, 1])
mlflow.log_params({"max_depth": depth, "n_features": X.shape[1]})
mlflow.log_metric("roc_auc", auc)
mlflow.set_tag("data_sha256_12", data_hash)
mlflow.sklearn.log_model(model, name="model")
print(f"depth={depth} auc={auc:.4f} run_id={run.info.run_id}")
if auc > best[1]:
best = (run.info.run_id, auc)
mlflow.register_model(f"runs:/{best[0]}/model", "churn")
json.dump({"roc_auc": best[1], "data_sha256_12": data_hash},
open("baseline.json", "w"), indent=2)
print("registered from run", best[0], "auc", round(best[1], 4))
Expected output: three depth=... auc=... lines, then a registered-model line naming version 1. Write down your AUC: it is the baseline build 2 defends.
Step 3: the promotion gate, which is the actual project
Registering a version is not promotion. Promotion is a deliberate act with a condition attached, and this is where most portfolios stop.
from mlflow import MlflowClient
client = MlflowClient(tracking_uri="http://127.0.0.1:5000")
TOL = 0.005 # allow this much noise, no more
candidate = max(client.search_model_versions("name='churn'"),
key=lambda v: int(v.version))
cand_auc = client.get_run(candidate.run_id).data.metrics["roc_auc"]
try:
champ = client.get_model_version_by_alias("churn", "champion")
champ_auc = client.get_run(champ.run_id).data.metrics["roc_auc"]
except Exception:
champ_auc = None
if champ_auc is None or cand_auc >= champ_auc - TOL:
client.set_registered_model_alias("churn", "champion", candidate.version)
print(f"promoted v{candidate.version} ({cand_auc:.4f})")
else:
print(f"BLOCKED v{candidate.version}: {cand_auc:.4f} "
f"below champion {champ_auc:.4f}")
raise SystemExit(1)
Use aliases, not stages. MLflow's tracking issue says registry stages were deprecated from 2.9 with removal planned for a later major release, so calling transition_model_version_stage in 2026 says you learned this from a 2022 tutorial.
Now make it demonstrable: rerun step 2 with max_depth=1 so the metric drops, run step 3, screenshot the BLOCKED line and its non-zero exit. That beats any diagram in your README.
What usually goes wrong here
Two things, every time. You forget the SQLite flag, get a cryptic registry error, lose twenty minutes. Then your installed versions drift from what MLflow logged beside the model, and load_model fails on a pickle from a different scikit-learn minor. Pin it now.
Building a CI/CD Pipeline for Machine Learning on 2,000 Free Minutes
A CI/CD pipeline for machine learning differs from an ordinary one in one way: what can regress is a number, not a test. The rest is normal continuous integration, so DevOps habits transfer.
The budget matters. GitHub's Free plan includes 2,000 Linux Actions minutes a month on private repositories and reports public ones as unlimited on standard runners, with Windows counting double and macOS tenfold. GitHub also cut per-minute runner rates on 1 January 2026 by up to 39% by machine type, which hits overage, not the quota. Make the repo public if you can.
# .github/workflows/model-ci.yml
name: model-ci
on:
pull_request:
paths: ["src/**", "requirements.txt", "baseline.json"]
jobs:
guard:
runs-on: ubuntu-latest
timeout-minutes: 12 # a runaway fit will not eat the month
steps:
- uses: actions/checkout@v5
- uses: actions/setup-python@v6
with:
python-version: "3.12"
cache: pip
- run: pip install -r requirements.txt
- run: pytest -q tests/test_features.py
- name: Train on the pinned slice
run: python src/train.py --slice data/ci_slice.parquet --out metrics.json
- name: Fail if the metric regressed
run: |
python - <<'PY'
import json, sys
new = json.load(open("metrics.json"))["roc_auc"]
base = json.load(open("baseline.json"))["roc_auc"]
print(f"candidate {new:.4f} vs baseline {base:.4f}")
if new < base - 0.005:
sys.exit(f"REGRESSION: {base - new:.4f} below tolerance")
PY
- uses: actions/upload-artifact@v4
if: always()
with:
name: metrics
path: metrics.json
Two details matter. timeout-minutes stops a hung job eating your month over a weekend, and if: always() keeps the metrics from failed runs. Workflow design at this level is drilled hands-on in 360DT's AWS DevOps programme and the AZ-400 track.
Where the hours actually go on build 1
Budget for the model and not the plumbing, and you overrun threefold.
Our scoping budget for live cohorts, not a published benchmark. Checked 7 November 2026.
Pick your deploy target before you write the Dockerfile
This trips people up right now. Per the Hub's Spaces documentation, Gradio and Docker Spaces run on compute and require a paid plan to create: PRO for a personal account, Team or Enterprise for an organisation. Free accounts in good standing get two ZeroGPU Gradio Spaces, Static Spaces stay free, and a free cpu-basic Space gives 16 GB RAM and 2 vCPU before sleeping at about 48 hours idle. Check your tier today.
Also read: if the Dockerfile is the part you are least sure of, work through Docker Tutorial for Beginners 2026 before build 3.
Model Drift Monitoring: The Project That Separates You From Everyone Else
Here is the asymmetry worth exploiting. Thousands of portfolios contain a deployed model. Almost none show the author would notice it going wrong. Build this one first if you build only one.
It is research territory rather than a solved tooling problem. Carnegie Mellon's Software Engineering Institute runs a project on predicting changing conditions in production ML systems and publishes Portend, an open source toolset that simulates drift and works out which metrics detect it.
The mechanics are simpler than the theory. Population Stability Index over quantile bins:
import numpy as np, pandas as pd
def psi(expected: pd.Series, actual: pd.Series, bins: int = 10) -> float:
"""PSI over quantile bins of the training distribution."""
edges = np.unique(np.quantile(expected.dropna(), np.linspace(0, 1, bins + 1)))
edges[0], edges[-1] = -np.inf, np.inf
e = np.histogram(expected, bins=edges)[0] / len(expected)
a = np.histogram(actual, bins=edges)[0] / len(actual)
e, a = np.clip(e, 1e-6, None), np.clip(a, 1e-6, None)
return float(np.sum((a - e) * np.log(a / e)))
train = pd.read_parquet("features/train.parquet")
live = pd.read_parquet("logs/predictions.parquet")
live = live[live.ts >= live.ts.max() - pd.Timedelta("1h")]
alerts = {c: round(psi(train[c], live[c]), 3)
for c in ("age", "balance", "duration")
if psi(train[c], live[c]) > 0.2}
if alerts:
print("DRIFT", alerts) # post this to a webhook
else:
print("stable", len(live), "rows")
Conventionally PSI under 0.1 is stable, 0.1 to 0.25 deserves a look, above 0.25 is a real shift. I use 0.2 because at portfolio volumes an hour of traffic is small enough that you want telling early. A threshold you can justify beats a textbook one you cannot.
To demonstrate it, poison a feature: add 15 years to every age in your request generator and capture the alert. For a dashboard, a Power BI report over the prediction log is fastest, and that modelling sits in 360DT's PL-300 course; the generative equivalent is in the AI Engineer course.
Also read: MLOps vs DevOps in 2026 if you are still deciding which of the two ladders to climb.
Where These MLOps Projects Go Wrong
A practitioner write-up updated in March 2026 describes a pipeline that retrained whenever any drift detector fired. One Tuesday morning the whole thing went into a retraining loop, because the model's own predictions were feeding back into its training features. That is the argument for build 6's human gate, and a better interview answer than "I automated retraining".
| Symptom | What is actually happening | The fix |
|---|---|---|
| Registry calls fail with an unsupported-backend error | MLflow is on the default file store, which has no registry | Start with --backend-store-uri sqlite:///mlflow.db
|
load_model raises a pickle error weeks later |
scikit-learn minor drifted between train and serve | Pin exact training versions and reuse the same requirements file |
| CI passes but the deployed model is the old one | The container pinned a version number, not the alias | Load models:/name@champion and restart on promotion |
| Drift alert fires constantly on day one | Window too small, so an hour of traffic is noise | Require a minimum row count, and widen the window |
| Actions minutes exhausted mid-month | Scheduled training on a private repo, or no timeout | Add timeout-minutes or make the repo public |
Two things to deliberately not build. Not Kubeflow: a weekend of cluster plumbing a reviewer never sees. Not a feature store, because a dated Parquet partition with a manifest proves the same point in an afternoon. Learn Kubernetes separately, as infrastructure, which is how the 360DT certifications overview sequences it.
How to Sequence the Builds, and What to Learn Alongside
Order matters more than selection: builds 2, 3, 4 and 6 all consume artefacts build 1 produces. Out of order, you rebuild the registry three times.
Build 1 first, in one sitting if you can. Then build 3, because a running service makes the loop observable and the rollback demo is the most quotable thing you will own. Build 2 third, once you have a baseline worth defending. Build 4 fourth and slowly, because that is the deep one. Build 5 for data engineering interviews, 6 last.
What to pair with MLOps portfolio projects
The projects teach the loop, not the cloud primitives underneath, and that is the gap interviewers probe second. Study two things alongside: managed orchestration on a real cloud, since local Docker teaches you nothing about compute quotas or managed identities, and pipeline work, because build 5 is a data engineering problem wearing an ML hat, which is why the Microsoft Fabric track overlaps so heavily with MLOps hiring. For generative systems, evaluation architecture is first-class in the CCAR-F prep.
If I were Meera, I would build 1 and 3 this month, put the rollback demo at the top of my CV and start interviewing rather than waiting for all six. Interviews tell you which of the remaining four to build, and that beats another month of unguided work. For the same loop with an engineer reviewing your pipeline, the live MLOps Engineer course mapped to AI-300 and CCAR-F runs weekends; a free webinar is the cheaper way to check the pitch.
Build the whole MLOps loop with an engineer reviewing your pipeline
Eight weeks of live weekend sessions on registries, deployment, monitoring and retraining, mapped to the Microsoft AI-300 and Claude CCAR-F exams. You build and defend the pipeline rather than watch one.
Explore the course
Related guides
- MLOps Engineer Interview Questions 2026 read once a build is done: the questions tell you which parts to lead with.
- MLOps Engineer Salary in India 2026 advertised bands by experience, so you know what the projects buy you.
- DevOps to MLOps Engineer in India 2026 the fastest route in if you already run pipelines.
- LLM Evaluation in 2026 the same gate-and-baseline thinking where accuracy metrics stop working.
Frequently asked questions
What are the best MLOps projects for a portfolio in 2026?
A tracked training run with a promotion gate, a containerised service that rolls back by moving an alias, and a drift monitor that fires a real alert. Those three cover what operations interviews test.
How long does an MLOps project take to build?
Between 8 and 20 hours each. Roughly a third goes on wiring, a quarter on dependency debugging, under a tenth on training. All six is about four months at 30 hours a month.
Can I do MLOps projects without a GPU?
Yes, and you should. Every build here runs on a laptop CPU with tabular data, because the subject is the pipeline. Keep a full retrain under two minutes so CI stays inside the free allowance.
Do I need Kubernetes for an MLOps project?
No, and for a portfolio I would avoid it. One container with a pinned model alias shows the same deployment and rollback thinking in a fraction of the time.
Is MLflow free to use?
Yes. It is open source and self-hosted with no account required, and the releases page lists 3.18.0 published on 4 November 2026. One catch: the registry needs a database backend, so use SQLite or Postgres.
Can a fresher get an MLOps job with projects alone?
Rarely, and it is worth being clear about that. Most Indian MLOps openings ask for several years of production experience. What the projects open up is the adjacent moves.
About this guide. 360 Digital Transformation is an Anthropic Partner and a Microsoft Authorized Training Partner. Other certification bodies, vendors and employers named here are not affiliated with us. Tools and versions change quickly; commands and figures cited were checked on 7 November 2026.




