Build a real fraud detection workflow with Crab
Start a seven-part ML series with a realistic fraud detection pipeline and the exact Crab CLI used to validate, run, inspect, and share it.
Imagine a payments team retrains a fraud classifier every week. The source code is small, but the transaction snapshot, feature table, and model are large. Reviewers need to know which data and parameters produced a model, while CI should avoid repeating an unchanged two-hour training job.
This series uses that same system from first pipeline run through production promotion:
transactions.csv → raw.csv → features.csv → fraud-model.pkl → metrics + plotCrab keeps the workflow declaration and small evidence in Git, large bytes in object storage, and reusable stage results in a content-addressed cache. No separate Crab data server sits between the team and its bucket.
Explore content-addressed invalidation
Scroll horizontally to explore the full diagram →
Every content-addressed stage key is new, so the complete DAG executes.
1. Create the project boundary
Start with a local Git repository. The complete example uses only the Python 3 standard library; copy it from the example source or create these files alongside the snippets below.
mkdir fraud-detection && cd fraud-detection
git init
mkdir -p data models metrics plots srcDownload or copy data/transactions.csv and every script under src/ from the
example source. The workflow runs locally without a Crab remote.
Use a small params.json for reviewable training inputs:
{
"features": {
"lookback_days": 30
},
"train": {
"algorithm": "logistic_regression",
"learning_rate": 0.2,
"l2": 0.01,
"max_iter": 800,
"seed": 42
},
"evaluate": {
"threshold": 0.5,
"minimum_recall": 0.82
}
}2. Declare the complete DAG
Each stage names its command, dependencies, parameter keys, and outputs. An output consumed by another stage creates a producer-to-consumer edge.
params:
- params.json
metrics:
- metrics/evaluation.json
plots:
- plots/precision_recall.csv:
x: recall
y: precision
artifacts:
fraud-model:
path: models/fraud-model.pkl
type: model
desc: Weekly card-not-present fraud classifier
labels: [fraud, payments]
stages:
ingest:
cmd: python3 src/ingest.py
deps:
- src/common.py
- src/ingest.py
- data/transactions.csv
outs:
- data/raw.csv
features:
cmd: python3 src/features.py --config params.json
deps:
- src/common.py
- src/features.py
- data/raw.csv
params:
- features.lookback_days
outs:
- data/features.csv
train:
cmd: python3 src/train.py --config params.json
deps:
- src/common.py
- src/train.py
- data/features.csv
params:
- train.algorithm
- train.learning_rate
- train.l2
- train.max_iter
- train.seed
outs:
- models/fraud-model.pkl
evaluate:
cmd: python3 src/evaluate.py --config params.json
deps:
- src/common.py
- src/evaluate.py
- models/fraud-model.pkl
- data/features.csv
params:
- evaluate.threshold
- evaluate.minimum_recall
metrics:
- metrics/evaluation.json
plots:
- plots/precision_recall.csv:
x: recall
y: precisionThe artifacts declaration names the model the organization cares about. The train stage remains responsible for producing its bytes. Artifact versioning comes later, after the workflow output is clean and recorded.
3. Validate before spending compute
Check the schema and graph without executing Python:
crab run --validate
crab workflow dag
crab workflow dag --format mermaid
crab stage listValidation catches cycles, duplicate outputs, invalid names, and malformed stage fields. The DAG should be a straight four-node path from ingest to evaluate.
You can also author simpler stages from the CLI:
crab stage add -n ingest \
--force \
-d src/common.py \
-d src/ingest.py \
-d data/transactions.csv \
-o data/raw.csv \
python3 src/ingest.pyEditing YAML directly is clearer for this example because it also declares params, metrics, plots, and the artifact catalog.
4. Preview, execute, and inspect
Preview the execution decision first:
crab run --dry --explain-missThen run the DAG locally:
crab run --parallelism 2 --json
crab workflow status --json
crab metrics show
crab plots show --json
python3 src/smoke_model.py
python3 src/check_quality_gate.pyThe first run writes crab.lock. That lockfile records the exact successful stage state. A second unchanged run should reuse matching results:
crab run --parallelism 2 --jsonAll four stage results should report "cache_hit": true.
Use the interactive diagram above to see why a training-code change reuses ingest and features but invalidates train and evaluate. Crab calculates each stage key from the declared command, dependencies, parameter values, and selected environment—not from timestamps or stage names alone.
5. Commit reproducible state
Commit declarations, scripts, params, the lockfile, and small review evidence:
git add crab.yaml crab.lock params.json data/ src/ metrics/ plots/
git commit -m "add fraud detection workflow"The commands through this point require only Git, Crab, and Python 3.
6. Configure remote sharing when needed
The following boundary requires a real crab:// remote that your account can
write. Substitute your organization and repository, then declare the large file
families as committed policy. The tutorial fixture is intentionally tiny; in a
production repository, configure these patterns before the first commit that
contains large datasets or models.
crab init crab://ml-platform/fraud-detection
crab track "data/**/*.csv"
crab track "models/**/*.pkl"
git add .gitattributes crab.toml
git commit -m "configure Crab storage policy"
crab push
crab workflow push-cache --all --jsonThe decisive proof uses a clean clone, because the producer workspace already has local outputs and cache entries:
cd ..
crab clone crab://ml-platform/fraud-detection fraud-review
cd fraud-review
crab run --cache-only
crab workflow status
crab metrics show--cache-only exits with code 3 if a required result is absent. That makes it useful in CI: a normal run could silently recompute and hide an incomplete cache publication.
Continue with How Crab decides what to rerun.
KNOWLEDGE PROOF
Check the decision, not your memory.
If only `src/train.py` changes, which stages should Crab need to execute?