AWS Builder Center
Architecting an End-to-End MLOps & Real-Time Student Risk Prediction Engine with Amazon SageMaker, TreeSHAP Explainability, and Amazon Bedrock

Architecting an End-to-End MLOps & Real-Time Student Risk Prediction Engine with Amazon SageMaker, TreeSHAP Explainability, and Amazon Bedrock

Production blueprint for K-12 student academic risk prediction on AWS: resolving a 35:1 class imbalance and target leakage across 98,996 records, benchmarking Logistic Regression, Decision Trees, Random Forest, and XGBoost, and automating governance with SageMaker Pipelines, Model Registry, PrivateLink, and Bedrock.

Solutions Architect | SWE | 12x AWS Certified | MSc Data Science & AI | Machine learning
Catching K-12 students before they fail a school term ( Final_grade ≤ 13  on a 20-point scale) is a delicate balance: missing a struggling student delays support, while flooding counselors with false alarms erodes trust. Taking a model from a local notebook into school operations on AWS requires leak-free data pipelines, a solid strategy for class imbalance, fast explainability, and strict privacy controls.

In the C4 Context View (L1) above, Counselors and Teachers get sub-10ms risk predictions and TreeSHAP explanations in their portal, while Lead ML Engineers manage retraining through Amazon SageMaker Pipelines. Student records flow into Amazon SageMaker Feature Store (Online + Offline Iceberg), and Amazon Bedrock ( Claude 3.5 Haiku  + Guardrails) turns top risk drivers into action plans:
1. Class Imbalance (35:1 Ratio): Across 98,996 records, only 2.22% ( 2,196 ) are High Risk ( Grade 1.0 ), vs. 19.80% Moderate ( Grade 2.0 ) and 77.98% Low Risk ( Grade 3.0 ). A default model hits 77.98% Accuracy while missing almost every failing student.
2. Zero Data Leakage & Train/Serve Skew: Scaling, outlier cleanup, and grade averages are fitted strictly on  X_train  in SageMaker Processing. All 27 features are stored in SageMaker Feature Store ( Offline Iceberg  for training +  Online Store   < 3 ms   GetRecord  lookups in production).
3. Sub-7ms Explainability & Action Plans: Native C++ TreeSHAP ( 0.50 ms ) pulls the top 4 risk drivers per student and feeds a rule matrix and Amazon Bedrock to draft Individualized Intervention Plans (IIPs).
4. Auditable Governance (ISO/IEC 23053) & Privacy: Network-isolated containers ( enable_network_isolation = true ), AWS PrivateLink, KMS CMK encryption,  HMAC-SHA256  tokenization, and SageMaker Model Registry gates keep student data protected.



1. Dataset Audit, Data Leakage Remediation & Feature Engineering

1.1 Unified Student Feature Schema (98,996 Records × 18 Attributes)

Six years of academic, attendance, portal, infirmary, behavioral, and tuition records ( 2019–2024 , Terms  1..4 ) form 98,996 student-term rows:
Feature / Column
Type
Range
Description & Source
 Student_Id 
 string 
 HMAC-SHA256 
Tokenized  id_grupo.id_persona  hashed before S3 ingestion
 Year_of_study  /  Term 
 int64 
 2019..2024  /  1..4 
School year and bimester/trimester ( 1  to  4 )
 Grado  /  Nivel 
 int64 
 3..17  /  1..3 
Grade level and stage ( 1  = Early,  2  = Primary,  3  = Secondary)
 Age 
 float64 
 3.0..20.0 
Student age at cutoff (412 ERP typos up to  108.04 )
 Sex  /  Guardian 
 float64 
 0, 1 
Biological sex ( 50.16% ) and parent legal guardian ( 90.02% )
 Siblings_cnt  /  Parents_cnt 
 int64 
 0..3  /  0..4 
Enrolled siblings ( 0.35 ) and registered parents ( 1.31 )
 Parent_interaction 
 float64 
 0.0..1.0 
Portal activity:  (logins + agenda + news + report_cards) / 4 
 Payment_ratio 
 float64 
 0.0..1.0 
Ratio of on-time tuition payments to billed installments
 Sickness_cnt  /  Alergies_cnt 
 int64 
 0..2  /  0..3 
Infirmary visits and documented allergies
 Classroom_transfer  /  School_change 
 int64 
 0, 1 
Classroom switch ( 0.85% ) or school transfer ( 0.48% )
 Awards_ratio  /  Summer_school 
 int64 
 -1..1  /  0, 1 
Conduct ( +1  merit,  -1  demerit) & summer school ( 1.81% )
 Final_grade  (Target  y )
 float64 
 1.0, 2.0, 3.0 
 1.0  = High Risk (≤13, 2.22%),  2.0  = Mod (19.80%),  3.0  = Low (77.98%)



1.2 Eliminating Target Leakage & Domain Outliers in SageMaker Processing

Auditing early notebooks showed why prototypes fail in production: a single column ( academic_trajectory ) held 43.66% of Gini importance, artificially inflating High-Risk Precision to  0.70  and ROC-AUC to  0.895 . Raw exports also had 412 corrupted  Age  rows ( 0.42% ) up to  108.04  years from birth-date typos.
1. Direct Target Leakage ( Final_grade.diff() ): Computing  Final_grade.diff()  before separating  y  embeds the current term's grade inside  X .
2. Full-Dataset Scaling Leakage: Running  groupby('Grado')  averages and  StandardScaler().fit_transform(df)  before splitting leaks test statistics into training.
3. Stateful Fix ( LeakFreeStudentFeatureEngineer ) & Feature Store: Cleaning and feature math run inside a Scikit-Learn transformer in SageMaker Processing, learning grade medians ( Age ∈ [3.0, 20.0] ), means, and standard deviations only on  X_train  ( 69,296  rows). The 27 leak-free features are ingested into SageMaker Feature Store ( student-academic-risk-fg-prod ), using the Offline Store (S3 Iceberg) for training and the Online Store for  < 3 ms   GetRecord  lookups:
Engineered Feature
Formula / Definition
Practical Meaning
 age_acceleration 
 Age / max(Grado, 1) 
Flags students older than expected for their grade
 age_zscore_in_grade 
 (Age - μ_train(Grado)) / σ_train(Grado) 
Age deviation vs. classmates (fitted on  X_train )
 grade_speed 
 Grado / max(Year_of_study - 2015, 1) 
Pace of grade progression across school years
 age_parent_interaction 
 Age × Parent_interaction 
Parent portal activity weighted by student age
 relative_parent_engagement 
 Parent_interaction - μ_train_parent(Grado) 
Parent portal usage vs. grade peers
 academic_support_index 
 Parent_interaction × Parents_cnt × (1 - School_change) 
Household support, portal activity, and stability
 risk_accumulation 
Sum of 6 binary flags ( Sickness ,  Payment , etc.)
Count of simultaneous health, payment, or conduct flags
 financial_engagement_index 
 Payment_ratio × (Parent_interaction + 0.1) 
Link between on-time tuition and portal activity
 mobility_stress_index 
 Classroom_transfer + (2 × School_change) + Summer_school 
Stress from switching classrooms/schools or summer school
 term_completion 
 Term / 4.0 
Point in the school year ( 0.25  to  1.0 )



2. Multi-Model Benchmarking & Solving the 35:1 Class Imbalance

2.1 Why Accuracy and ROC-AUC Mislead on a 2.22% Minority Class

With  77.98%  Low Risk,  19.80%  Moderate Risk, and  2.22%  High Risk students, standard Accuracy and ROC-AUC hide bad performance on failing students because non-failing students outnumber failing ones by 35 to 1. The SageMaker Pipeline Gate therefore evaluates PR-AUC (High Risk), High-Risk Recall ( Recall_Class_1 ), Macro F1, and p99 Latency.

2.2 Benchmark Across 4 Model Families & 3 Imbalance Strategies (SageMaker Script Mode)

This architecture runs SageMaker Managed Containers in Script Mode ( sagemaker-scikit-learn:1.2-1  and  sagemaker-xgboost:1.7-1 ). AWS handles image patching and C++ runtime tuning, while custom scripts ( train_xgboost.py ,  inference.py ) control sample weights, threshold tuning, and SHAP extraction across the leak-free splits ( Train = 69,296 ,  Val = 9,900 ,  Test = 19,800 ):
1. Global Classification & Inference Latency ( Test = 19,800 ):


2.3 Key Engineering Takeaways from the Benchmark

  1. Why Unweighted Models Fail: Unweighted Random Forest and XGBoost reach  > 80%  accuracy, yet High-Risk Recall is only  8.88%  and  13.44%  ( 2.28%  in Logistic Regression). 86% to 97% of failing students are missed because standard loss functions optimize for the  77.98%  Low-Risk majority.
  1. Why Full SMOTE ( k=5 ) Hurts Precision: Oversampling all classes to  [54,039 × 3]  with  SMOTE  pushes Random Forest Recall to  50.34% , but drops accuracy from  80.18%  to  69.71%  and cuts High-Risk Precision to  20.95% . Interpolating across discrete whole-number features ( Term ,  Grado ,  Awards_ratio ,  Summer_school ) creates unrealistic synthetic students, lowering PR-AUC ( 0.2687 → 0.2472 ).
  1. Why Cost-Sensitive XGBoost + Threshold Tuning ( τ_high = 0.33 ,  τ_mod = 0.41 ) Wins: Sample weights ( {High: 5.5, Mod: 1.8, Low: 1.0} ) with regularized trees ( max_depth=6 ,  min_child_weight=10 ,  gamma=0.2 ,  reg_lambda=2.0 ) and threshold tuning boost High-Risk Recall by 3.3× ( 13.44% → 43.96% ) while keeping  77.25%  accuracy,  PR-AUC = 0.2875 ,  0.21 ms  p99 latency (66× faster than RF), and  0.50 ms  C++ TreeSHAP.



Architecture Decision Record: Model Family & Imbalance Strategy Selection

Architecture Decision Record (ADR-01: Cost-Sensitive XGBoost vs. SMOTE & Deep Tabular Models):
  • Context: Classify K-12 students into 3 risk tiers across 98,996 rows with a 35:1 imbalance ( 2.22%  High Risk), discrete features, and a  < 25 ms  p99 SLA.
  • Decision: Use SageMaker XGBoost ( 1.7-1  Script Mode) with weights ( {1: 5.5, 2: 1.8, 3: 1.0} ), tuned cutoffs ( τ_high = 0.33 ,  τ_mod = 0.41 ), and native  pred_contribs=True  TreeSHAP.
  • Rejected Alternatives:
  • Random Forest + SMOTE ( k=5 ): Cut accuracy by  -10.47%  ( 80.18% → 69.71% ), lowered PR-AUC ( 0.2875 → 0.2472 ), and ran 66× slower at p99 ( 13.99 ms  vs.  0.21 ms ).
  • Deep Tabular Neural Networks (MLP / TabNet): Need GPU instances ( ml.g4dn.xlarge , ~3.8× cost), underperform GBDTs on  < 100k  discrete rows, and lack sub-ms TreeSHAP.
  • Trade-Off Accepted: Accepting  28.55%  High-Risk Precision (~2.5 check-ins per failing student) and threshold tuning to catch 43.96% of High-Risk students (3.3× recall gain) at  0.21 ms  p99.



3. Multi-Tier Cloud Architecture & Topology Diagrams

Building on the C4 Context View (L1) at the start, the AWS infrastructure is organized into three views covering MLOps workflows, production security, and network isolation.

3.1 High-Level MLOps & Real-Time Inference Topology

  • Online Inference Path: Requests hit API Gateway ( /predict-risk ) secured by WAF and Cognito JWT. A Lambda Orchestrator hashes  Student_Id , pulls the 27 features in  < 3 ms  from SageMaker Feature Store (Online) via  GetRecord , and calls the SageMaker Real-Time Endpoint ( ml.m5.large ) over PrivateLink for probabilities and top 4 TreeSHAP factors ( ~6.88 ms ). When  include_bedrock_narrative = true  for High/Moderate risk, it calls Amazon Bedrock ( Claude 3.5 Haiku  + Guardrails) to draft an action plan.
  • Offline MLOps Path: Term records in Amazon S3 trigger a SageMaker Pipeline that runs leak-free preprocessing, updates SageMaker Feature Store (Online + Offline Iceberg), trains XGBoost on Managed Spot Instances, checks PR-AUC and Recall, and registers passing models in Model Registry. Approvals trigger EventBridge to run 20% Canary Blue/Green deployments.


3.2 End-to-End Production Architecture

  1. Encryption & Privacy: A dedicated AWS KMS CMK encrypts S3, Feature Store, EBS volumes, Data Capture, and Bedrock Guardrails. CloudWatch Logs Data Protection masks accidental PII in logs.
  1. Drift & Fairness Monitoring: The endpoint saves 100% Data Capture to S3. SageMaker Model Monitor compares live inputs against  statistics.json  /  constraints.json , while SageMaker Clarify tracks SHAP Attribution Drift and fairness across  Sex  and  Guardian .
  1. Automated Retraining Loop: If Model Monitor or  HighRiskPredictionRate > 15%  breaches for 2 windows, CloudWatch Alarms trigger EventBridge to rerun  StudentAcademicRiskMLOpsPipeline .


3.3 Zero-Trust Network & VPC Segmentation Topology

To protect student data under FERPA, all workloads run inside an isolated VPC ( 10.50.0.0/16 ) across  us-east-1a  and  us-east-1b  with no Internet Gateways (IGW) and no NAT Gateways:
  • Private Orchestration Subnets ( 10.50.10.0/24 ,  10.50.20.0/24 ): Host Lambda ENIs ( sg-lambda-orch ), AWS PrivateLink Endpoints ( sg-vpce-privatelink ) ( sagemaker.runtime ,  sagemaker.api ,  sagemaker.featurestore-runtime ,  bedrock-runtime ,  ecr ,  kms ,  logs ,  monitoring ), and a free S3 Gateway Endpoint ( pl-63a5400a ).
  • Isolated SageMaker Subnets ( 10.50.100.0/24 ,  10.50.200.0/24 ): Run Real-Time Endpoints ( sg-sagemaker-rt ) and Pipeline jobs ( sg-sagemaker-jobs ) with  enable_network_isolation = true  and TLS 1.3 encryption.




Architecture Decision Record: Real-Time Endpoint vs. Serverless & Batch Inference

Architecture Decision Record (ADR-02: Auto-Scaled SageMaker Real-Time Endpoint vs. Serverless & Batch):
  • Context: Counselors query profiles live during grading and parent meetings, needing  < 25 ms  latency, Model Monitor Data Capture, and private VPC networking.
  • Decision: Deploy XGBoost + TreeSHAP on a SageMaker Real-Time Endpoint ( ml.m5.large ) in isolated VPC subnets with Auto Scaling ( 1..4  instances) and 100% Data Capture.
  • Rejected Alternatives:
  • SageMaker Serverless Inference: Suffers  1.5s–4.0s  cold starts and lacks VPC isolation ( VpcConfig ) and native Data Capture.
  • Nightly Batch Transform Only: Cannot recalculate risk live when a counselor logs a new incident or parent meeting.
  • Trade-Off Accepted: Paying ~$62.10/month with scheduled school-hour scaling for zero cold starts ( 6.88 ms  latency), PrivateLink isolation, and 100% Data Capture.



4. Explainable AI (TreeSHAP) & Prescriptive Intervention Engine with Amazon Bedrock

4.1 Global vs. Local TreeSHAP Feature Attributions

The endpoint uses XGBoost's C++  pred_contribs=True  engine, computing exact TreeSHAP log-odds values for all 3 classes in  0.501 ms  per student:
Rank
Feature Name
Category
Mean  |TreeSHAP| 
Practical Meaning
1
 Age 
Demographic
0.3516
Being older than expected for the grade points to prior repetition
2
 grade_speed 
Progression
0.3489
Slower progression across school years ( Grado / Years ) raises risk
3
 Year_of_study 
Cohort
0.3022
Captures grading shifts between pandemic and post-pandemic years
4
 relative_parent_engagement 
Engagement
0.1541
Lower parent portal activity compared to same-grade peers
5
 age_zscore_in_grade 
Peer Z-Score
0.1446
Students  > +1.5 SD  older than classmates face higher failure risk
6
 age_acceleration 
Progression
0.1263
Ratio between chronological age and current grade
7
 Grado  /  Sex 
Stage / Demo
0.1235 / 0.1059
Secondary transition variance;  Sex  audited via SageMaker Clarify
8
 Term  /  risk_accumulation 
Multi-Factor
0.1004 / 0.0773
Term grading pressure and combined health, payment, or transfer flags
9
 Awards_ratio  /  age_parent 
Conduct
0.0516 / 0.0428
Demerits ( -1 ) raise risk; active parent portal oversight protects

4.2 Turning SHAP Values into Action Plans: Rule Matrix + Amazon Bedrock

  1. Step 1 - School Rule Matrix ( DetailedInterventionSystem ,  < 1 ms ): Matches top positive TreeSHAP drivers ( shap_log_odds > 0 ) to school interventions ( parent_engagement ,  academic_progression ,  mobility_or_remedial ), assigning SLAs ( 48h  or  2-Week ), staff owners, and KPIs.
  1. Step 2 - Summary with Amazon Bedrock ( Claude 3.5 Haiku  + Guardrails,  ~420 ms  when requested): Sends  student_token , probabilities, top 4 SHAP values, and the matched protocol to Amazon Bedrock with a FERPA Guardrail scrubbing PII ( NAME ,  EMAIL ,  PHONE ).



Architecture Decision Record: Hybrid Prescriptive Engine vs. Pure LLM Risk Scoring

Architecture Decision Record (ADR-03: Hybrid TreeSHAP + Rule Matrix + Amazon Bedrock vs. Direct LLM Risk Prediction):
  • Context: Counselors need calibrated risk probabilities and natural-language action plans tailored to each student's risk factors.
  • Decision: Keep risk scoring and rule matching 100% deterministic in SageMaker (XGBoost + TreeSHAP +  DetailedInterventionSystem ), and use Amazon Bedrock Claude 3.5 Haiku ( temperature = 0.1  + Guardrails) only to draft the counselor summary when requested.
  • Rejected Alternatives:
  • Direct LLM Risk Scoring: Poorly calibrated on tabular numbers, cannot enforce PR-AUC cutoffs on a 35:1 imbalance, ~100× costlier, and can hallucinate.
  • Static Templates Only: Cannot weave multi-factor interactions ( School_change  + high  age_zscore_in_grade ) into a cohesive brief.
  • Trade-Off Accepted: Adding  ~420 ms  latency and  ~$0.0008  token cost only when  include_bedrock_narrative = true , keeping default scoring at  6.88 ms .



5. Automated MLOps Governance with SageMaker Pipelines & Model Registry


  1. Step 1 -  LeakFreeFeatureEngineeringAndFeatureStoreIngest  ( ProcessingStep ): Runs  SKLearnProcessor  on  ml.m5.xlarge  in private subnets. Fixes the 412  Age  outliers using  X_train  medians, computes the 10 engineered features, ingests all 27 features into SageMaker Feature Store ( Online + Offline Iceberg ), exports splits to S3, and writes  statistics.json  /  constraints.json .
  1. Step 2 -  TrainCostSensitiveXGBoost  ( TrainingStep ): Trains SageMaker XGBoost  1.7-1  with Managed Spot Training ( ~70%  savings) and weights  {0: 5.5, 1: 1.8, 2: 1.0} .
  1. Step 3 -  EvaluateAndCalibrateThresholds  ( ProcessingStep ): Evaluates on the  19,800  test rows, tunes  (τ_high, τ_mod) , checks TreeSHAP speed, and writes  evaluation.json .
  1. Step 4 -  CheckHighRiskRecallAndPrAuc  ( ConditionStep ): Inspects  evaluation.json  via  JsonGet ; only proceeds if  Recall_Class_1 ≥ 0.44  and  PR_AUC_Class_1 ≥ 0.28 .
  1. Step 5 -  RegisterStudentRiskModel  & Canary Rollout: Registers the package in  student-academic-risk-models  ( PendingManualApproval ). Upon approval, EventBridge launches a 20% Canary deployment with CloudWatch  5XX  auto-rollback.



Aligning AWS MLOps Governance with ISO/IEC 23053 (AI Systems Using Machine Learning)

Mapping every Amazon SageMaker step to ISO/IEC 23053 (Framework for AI Systems Using Machine Learning) gives cloud engineers and institutional auditors a shared checklist:
ISO/IEC 23053 Stage
AWS / SageMaker Implementation
Practical Engineering & Audit Guarantee
1. Data Prep & Feature Store
 SageMaker Processing  +  Feature Store  ( Online  +  Iceberg )
Zero target leakage ( X_train  fit), zero train-serve skew ( GetRecord ), age fix, and  HMAC-SHA256  hashing.
2. Modeling & Training
 SageMaker Training Job  ( XGBoost   {5.5, 1.8, 1.0} )
KMS-encrypted  model.tar.gz  artifacts with tracked hyperparameters and weights.
3. Verification & Validation
 EvaluationStep  +  ConditionStep  ( PR-AUC ≥ 0.25 ,  Recall ≥ 0.40 )
Automated quality gate ( evaluation.json ) blocking weak models from registration.
4. Model Repository & Lineage
 SageMaker Model Registry  ( student-academic-risk-models )
Approval state machine ( PendingManualApproval → Approved ) with dataset and image lineage.
5. Deployment & Explainability
 Real-Time Endpoint  + Native  TreeSHAP  +  Amazon Bedrock 
Sub-7ms predictions with exact per-student SHAP ( 0.50 ms ) and guardrailed action plans.
6. Continuous Monitoring
 SageMaker Model Monitor  ( 100%  Capture) +  SageMaker Clarify 
Ongoing data drift checks ( constraints.json ) and fairness audits across  Sex  and  Grado .



Architecture Decision Record: SageMaker Pipelines + Model Registry vs. Notebook Deployments

Architecture Decision Record (ADR-04: Governed SageMaker Pipelines & Model Registry vs. Ad-Hoc Notebook Deployments):
  • Context: Risk models are retrained each term ( Term 1..4 ). Manual notebook retraining previously caused untracked changes and target leakage ( Final_grade.diff() ).
  • Decision: Automate retraining via SageMaker Pipelines and Model Registry, with an IAM rule blocking  sagemaker:UpdateEndpoint  unless the package is  Approved .
  • Rejected Alternatives:
  • Direct  estimator.deploy()  from Notebooks: No lineage, prone to leakage/skew, and no metric gate.
  • Self-Managed Kubeflow / Airflow on EKS: Adds $140+/month in cluster overhead unnecessary for term-based tabular retraining.
  • Trade-Off Accepted: Writing ~200 lines of Python SDK pipeline code upfront while paying $0.00/month in orchestration fees.



6. Implementation Code: Feature Pipeline, Inference Handler & Terraform IaC

A. Leak-Free Feature Engineering Transformer ( src/benchmark_models.py )

Python
from sklearn.base import BaseEstimator, TransformerMixin
from sklearn.preprocessing import StandardScaler
import pandas as pd

class LeakFreeStudentFeatureEngineer(BaseEstimator, TransformerMixin):
def __init__(self, min_age: float = 3.0, max_age: float = 20.0):
self.min_age, self.max_age = min_age, max_age
self.scaler_ = StandardScaler()
self.cols_ = [
"age_acceleration", "age_parent_interaction", "grade_speed", "age_zscore_in_grade",
"relative_parent_engagement", "academic_support_index", "risk_accumulation",
"term_completion", "financial_engagement_index", "mobility_stress_index",
]

def fit(self, X: pd.DataFrame, y=None):
v = X[(X["Age"] >= self.min_age) & (X["Age"] <= self.max_age)]
self.global_med_ = float(v["Age"].median())
self.grade_meds_ = v.groupby("Grado")["Age"].median().to_dict()
st = v.groupby("Grado")["Age"].agg(["mean", "std"]).to_dict(orient="index")
self.grade_stats_ = {g: (float(s["mean"]), max(float(s["std"] or 1.0), 1e-6)) for g, s in st.items()}
self.parent_means_ = X.groupby("Grado")["Parent_interaction"].mean().to_dict()
self.scaler_.fit(self._compute(X)[self.cols_])
return self

def _compute(self, X: pd.DataFrame) -> pd.DataFrame:
df = X.copy()
inv = (df["Age"] < self.min_age) | (df["Age"] > self.max_age)
if inv.any():
df.loc[inv, "Age"] = df["Grado"].map(self.grade_meds_).fillna(self.global_med_)[inv]
df["age_acceleration"] = df["Age"] / df["Grado"].clip(lower=1)
df["age_parent_interaction"] = df["Age"] * df["Parent_interaction"]
df["grade_speed"] = df["Grado"] / (df["Year_of_study"] - 2015).clip(lower=1)
gm = df["Grado"].map(lambda g: self.grade_stats_.get(g, (self.global_med_, 1.0))[0])
gs = df["Grado"].map(lambda g: self.grade_stats_.get(g, (self.global_med_, 1.0))[1])
df["age_zscore_in_grade"] = (df["Age"] - gm) / gs
df["relative_parent_engagement"] = df["Parent_interaction"] - df["Grado"].map(self.parent_means_).fillna(0.108)
df["academic_support_index"] = df["Parent_interaction"] * df["Parents_cnt"] * (1 - df["School_change"])
df["risk_accumulation"] = (
(df["Sickness_cnt"] > 0).astype(int) + (df["Parent_interaction"] == 0).astype(int)
+ (df["School_change"] > 0).astype(int) + (df["Payment_ratio"] == 0).astype(int)
+ (df["Awards_ratio"] < 0).astype(int) + (df["Summer_school"] > 0).astype(int)
)
df["term_completion"] = df["Term"] / 4.0
df["financial_engagement_index"] = df["Payment_ratio"] * (df["Parent_interaction"] + 0.1)
df["mobility_stress_index"] = df["Classroom_transfer"] + 2 * df["School_change"] + df["Summer_school"]
return df

def transform(self, X: pd.DataFrame) -> pd.DataFrame:
df = self._compute(X)
df[self.cols_] = self.scaler_.transform(df[self.cols_])
return df

B. Real-Time Inference Handler ( src/inference.py )

Python
import hashlib, hmac, json, os, time
import boto3, joblib, numpy as np, pandas as pd, xgboost as xgb

REGION = os.environ.get("AWS_REGION", "us-east-1")
FG_NAME = os.environ.get("FEATURE_GROUP_NAME", "student-academic-risk-fg-prod")
SECRET = os.environ.get("STUDENT_ID_HMAC_SECRET", "ferpa-kms-injected-salt")

def fetch_online_features(token: str) -> dict:
fs = boto3.client("sagemaker-featurestore-runtime", region_name=REGION)
resp = fs.get_record(FeatureGroupName=FG_NAME, RecordIdentifierValueAsString=token)
return {i["FeatureName"]: float(i["ValueAsString"]) for i in resp.get("Record", [])
if i["FeatureName"] not in ("Student_Token", "Event_Time")}

def model_fn(model_dir: str):
fe = joblib.load(os.path.join(model_dir, "feature_engineer.joblib"))
model = xgb.XGBClassifier()
model.load_model(os.path.join(model_dir, "xgboost_student_risk.json"))
with open(os.path.join(model_dir, "thresholds.json")) as f:
th = json.load(f)
return {"fe": fe, "model": model, "booster": model.get_booster(), "th": th}

def predict_fn(payload: dict, art: dict) -> dict:
t0 = time.perf_counter()
raw_id = str(payload.get("student_id", "anonymous"))
token = hmac.new(SECRET.encode(), raw_id.encode(), hashlib.sha256).hexdigest()[:16]
df_X = art["fe"].transform(pd.DataFrame([payload["student_features"]]))
cols, X_mat = list(df_X.columns), df_X.values

p_high, p_mod, p_low = [float(x) for x in art["model"].predict_proba(X_mat)[0]]
risk = "High Risk" if p_high >= art["th"].get("tau_high_risk", 0.33) else (
"Moderate Risk" if p_mod >= art["th"].get("tau_mod_risk", 0.41) else "Low Risk")

shap_vals = art["booster"].predict(xgb.DMatrix(X_mat, feature_names=cols), pred_contribs=True)[0, 0, :-1]
top_idx = np.argsort(np.abs(shap_vals))[::-1][:4]
top_shap = [{"feature": cols[i], "value": round(float(X_mat[0, i]), 3),
"shap_log_odds": round(float(shap_vals[i]), 4)} for i in top_idx]

plan = DetailedInterventionSystem.map_shap_drivers_to_actions(top_shap, risk)
brief = synthesize_bedrock_narrative(token, risk, [p_high, p_mod, p_low], top_shap, plan) if (
payload.get("include_bedrock_narrative") and risk != "Low Risk") else None

return {
"student_token": token, "risk_level": risk,
"probabilities": {"High": round(p_high, 4), "Mod": round(p_mod, 4), "Low": round(p_low, 4)},
"top_shap_attributions": top_shap, "intervention_plan": plan,
"bedrock_counselor_brief": brief, "latency_ms": round((time.perf_counter() - t0) * 1000, 2),
}

Verified Output ( 6.88 ms  End-to-End Execution)

JSON
{
"student_token": "50cf366653e07d5c", "risk_level": "Low Risk",
"probabilities": {"High": 0.1992, "Mod": 0.2028, "Low": 0.5980},
"top_shap_attributions": [
{"feature": "School_change", "value": 1.0, "shap_log_odds": 1.0480},
{"feature": "Summer_school", "value": 1.0, "shap_log_odds": -1.0274},
{"feature": "age_zscore_in_grade", "value": 5.471, "shap_log_odds": 0.3696},
{"feature": "Age", "value": 14.8, "shap_log_odds": 0.3655}
],
"intervention_plan": {"priority": "Standard Monitoring", "recommended_actions": [
{"what": "Transition & Classroom Integration", "when": "Weekly (4 wks)", "who": "School Psychologist"}
]},
"bedrock_counselor_brief": null, "latency_ms": 6.88
}

C. Production Infrastructure Blueprint ( iac/main.tf )

HCL
resource "aws_kms_key" "student_risk_cmk" {
description = "CMK for Student Risk S3, Feature Store, EBS, and Data Capture"
deletion_window_in_days = 30
enable_key_rotation = true
}

resource "aws_vpc_endpoint" "mlops_privatelink" {
for_each = toset([
"com.amazonaws.us-east-1.sagemaker.runtime", "com.amazonaws.us-east-1.sagemaker.api",
"com.amazonaws.us-east-1.sagemaker.featurestore-runtime", "com.amazonaws.us-east-1.bedrock-runtime",
"com.amazonaws.us-east-1.ecr.api", "com.amazonaws.us-east-1.ecr.dkr", "com.amazonaws.us-east-1.logs"
])
vpc_id = var.vpc_id
service_name = each.value
vpc_endpoint_type = "Interface"
subnet_ids = var.private_subnet_ids
security_group_ids = [aws_security_group.sagemaker_endpoint_sg.id]
private_dns_enabled = true
}

resource "aws_sagemaker_feature_group" "student_risk_fg" {
feature_group_name = "student-academic-risk-fg-${var.environment}"
record_identifier_feature_name = "Student_Token"
event_time_feature_name = "Event_Time"
role_arn = aws_iam_role.sagemaker_execution_role.arn
online_store_config {
enable_online_store = true
security_config { kms_key_id = aws_kms_key.student_risk_cmk.arn }
}
offline_store_config {
table_format = "Iceberg"
s3_storage_config {
s3_uri = "s3://sagemaker-student-risk-mlops-${var.environment}/feature-store"
kms_key_id = aws_kms_key.student_risk_cmk.arn
}
}
}

resource "aws_sagemaker_model" "student_risk_xgb" {
name = "student-risk-xgb-${var.environment}"
execution_role_arn = aws_iam_role.sagemaker_execution_role.arn
enable_network_isolation = true
primary_container {
model_package_name = var.approved_model_package_arn
environment = {
BEDROCK_MODEL_ID = "anthropic.claude-3-5-haiku-20241022-v1:0"
BEDROCK_GUARDRAIL_ID = aws_bedrock_guardrail.student_intervention_guardrail.guardrail_id
}
}
vpc_config {
subnets = var.private_subnet_ids
security_group_ids = [aws_security_group.sagemaker_endpoint_sg.id]
}
}

resource "aws_sagemaker_endpoint_configuration" "student_risk_config" {
name = "student-risk-ep-config-${var.environment}"
kms_key_id = aws_kms_key.student_risk_cmk.arn
production_variants {
variant_name = "PrimaryXGBoostTreeSHAP"
model_name = aws_sagemaker_model.student_risk_xgb.name
initial_instance_count = 1
instance_type = "ml.m5.large"
}
data_capture_config {
enable_capture = true
initial_sampling_percentage = 100
destination_s3_uri = "s3://sagemaker-student-risk-mlops-${var.environment}/data-capture"
kms_key_id = aws_kms_key.student_risk_cmk.arn
capture_options { capture_mode = "Input" }
capture_options { capture_mode = "Output" }
}
}

resource "aws_sagemaker_endpoint" "student_risk_endpoint" {
name = "student-academic-risk-rt-${var.environment}"
endpoint_config_name = aws_sagemaker_endpoint_configuration.student_risk_config.name
deployment_config {
blue_green_update_policy {
traffic_routing_configuration {
type = "CANARY"
wait_interval_in_seconds = 300
canary_size {
type = "CAPACITY_PERCENT"
value = 20
}
}
termination_wait_in_seconds = 300
}
auto_rollback_configuration {
alarms { alarm_name = aws_cloudwatch_metric_alarm.endpoint_5xx_errors.alarm_name }
}
}
}



7. Production Observability, Drift Detection & Student Data Privacy (FERPA)

Running a student risk model across school years means watching for feature drift, grading shifts, and broken ERP feeds:
  1. Catching Broken ERP Syncs with CloudWatch EMF: If an ERP update breaks parent portal sync,  Parent_interaction  drops to  0.0  (#4 TreeSHAP driver), causing a spike in High-Risk flags. Lambda emits  HighRiskPredictionRate ; if the 1-hour rate exceeds  15.0%  (vs.  2.22%–6.5%  baseline), CloudWatch alerts the team before counselors see bad alerts.
  1. Model Monitor & Clarify Drift: Daily Data Quality jobs check  constraints.json  bounds ( 3.0 ≤ Age ≤ 20.0 ,  0.0 ≤ Payment_ratio ≤ 1.0 ). Weekly Clarify jobs check NDCG on the TreeSHAP ranking and trigger EventBridge retraining if key drivers shift.
  1. Protecting Minor PII (FERPA): Student names, IDs, and addresses never enter S3 or SageMaker.  Student_Id  is hashed via  HMAC-SHA256  with a KMS salt, and Bedrock Guardrails scrub PII before generating notes.



8. Cost & TCO Optimization

Combining Managed Spot Training, Scheduled Endpoint Auto-Scaling ( 07:00–19:00 Mon–Fri ), and on-demand Bedrock Haiku calls keeps the full production setup at  $112.60/month :
AWS Service / Component
Sizing & Utilization
Optimization Lever
Monthly Cost
SageMaker Real-Time Endpoint
 1 × ml.m5.large , scaled down off-hours
Scheduled + Target Auto-Scaling
$62.10
SageMaker Pipelines & Training
 ml.m5.xlarge  Processing + XGBoost
Spot Training (70% off) +  $0  DAG
$1.85
SageMaker Feature Store
Online ( <3 ms ) + Offline S3 Iceberg
Eliminates train-serve skew
$4.18
SageMaker Monitor & Clarify
Weekly runs ( 4 × 15 min/mo )
Matches grading cadence
$0.46
Amazon Bedrock ( Haiku 3.5 )
 ~6,000  narratives/mo + Guardrail
Only when  risk != Low  & requested
$4.92
AWS PrivateLink & S3 Gateway
VPC Interface Endpoints + Free S3 Gateway
Avoids NAT Gateway data fees
$28.80
S3, KMS CMK & CloudWatch
 15 GB  lake + Data Capture, CMK, Alarms
S3 Intelligent-Tiering
$10.29
Total Production TCO
End-to-End MLOps + Feature Store + Bedrock
~63% savings vs. 24/7 setup
$112.60 / mo



9. Architecture Trade-Offs Summary (ADR Table)

ADR Ref
Decision
Alternatives
Trade-Off Accepted
Primary Benefit
ADR-01
Cost-Sensitive XGBoost + Threshold ( τ = 0.33 )
RF +  SMOTE (k=5) , Deep MLP
 28.55%  Precision + threshold step
3.3× Recall gain ( 43.96% ),  PR-AUC = 0.2875 ,  0.21 ms  p99,  0.50 ms  TreeSHAP
ADR-02
Auto-Scaled Real-Time Endpoint ( ml.m5.large )
Serverless, Batch Transform
 ~$62.10/mo  baseline compute
Zero cold starts ( 6.88 ms ), PrivateLink isolation, 100% Data Capture
ADR-03
Hybrid Engine (TreeSHAP + Rules + Bedrock)
Direct LLM Scoring, Static Text
 +420 ms  &  ~$0.0008  on demand
100% deterministic scoring + guardrailed counselor action plans
ADR-04
SageMaker Pipelines + Registry ( ConditionStep )
Notebook  deploy() , EKS Airflow
~200 LOC SDK pipeline code
Blocks leaked/weak models, full lineage, Canary rollback, $0 idle fee



10. Conclusion & Production Verification Checklist

Taking a student risk model from a notebook into Amazon SageMaker shows that clean data pipelines and solid MLOps matter just as much as algorithm choice. Fixing target leakage ( Final_grade.diff() ), cleaning birth-date typos on  X_train , storing features in SageMaker Feature Store, using cost-sensitive XGBoost instead of blind  SMOTE , and combining TreeSHAP with Amazon Bedrock gives schools a fast, transparent tool to help struggling students early.

Production Readiness Checklist

  • [x] Zero Data Leakage: Medians, Z-scores, and  StandardScaler  fit strictly on  X_train  and stored in SageMaker Feature Store.
  • [x] Imbalance Metrics First: Pipeline  ConditionStep  enforces Class-1 Recall ( ≥ 0.44 ) and PR-AUC ( ≥ 0.28 ) over Accuracy.
  • [x] Sub-10 ms Explainability: Native C++  pred_contribs=True  computes local TreeSHAP values in  0.50 ms  per student.
  • [x] Private VPC Networking: Containers run with  enable_network_isolation = true , TLS 1.3 encryption, and AWS PrivateLink.
  • [x] Student Privacy & Guardrails:  HMAC-SHA256  ID hashing, KMS CMK encryption, CloudWatch Data Protection, and Bedrock Guardrails.
Any opinions in this article are those of the individual author and may not reflect the opinions of AWS.
Enjoyed reading this content? Let the author know!

Your likes, comments, shares, and saves help creators reach more builders.

Loading recommendations

Loading article