Dry Cleaning Prediction Model in Practice: From a Shopping Pain Point to Full Serverless ML Deployment

End-to-end ML project predicting garment dry cleaning needs, deployed on AWS Serverless with real-world lessons.
A developer frustrated by missing care labels on an online fashion platform built a full machine wash prediction model. This article reviews the complete pipeline — from data scraping and model training to AWS Serverless deployment — covering Lambda cold start challenges, class imbalance strategies, label noise from brand marketing, and MLflow model management, offering practical lessons for ML engineers.
An ML Project Born from a Shopping Pain Point
Have you ever struggled to find care labels when buying high-end clothing online? A developer (GitHub user sogofunmi) was inspired by exactly this problem. While shopping on Cult Mia, a high-end multi-brand retail platform, he noticed that most garments didn't include care instructions. So he decided to build a Machine Wash Prediction Model that automatically determines whether a garment needs to be dry cleaned.
The project ultimately shipped as a complete web application (machine-wash-or-not.com), backed by a full ML engineering pipeline covering data scraping, model training, automated retraining, and cloud deployment. Although the author modestly calls it a side project, the completeness of its technical implementation is worth studying for any AI engineering practitioner — it honestly showcases the many pitfalls encountered on the journey from idea to production deployment.
Technical Architecture: Serverless ML Pipeline Design
The author adopted a fairly typical AWS Serverless architecture to host the entire application — a mainstream choice for reducing operational costs in small-to-medium ML projects. Serverless doesn't literally mean "no servers." Instead, it means server management, scaling, and operations are entirely handled by the cloud provider, allowing developers to focus solely on business logic. The core advantage is pay-per-use pricing — no charges when there are no requests — which is especially friendly for personal projects and MVP validation where traffic is unpredictable.
Decoupled Frontend and Backend Deployment
The frontend uses S3 + CloudFront to host static assets. Amazon S3 (Simple Storage Service) is AWS's object storage service that can host HTML, CSS, JavaScript, and other static files while serving them directly over the web. CloudFront is AWS's Content Delivery Network (CDN), with over 400 edge locations worldwide that cache static assets at nodes closest to users, significantly reducing access latency. With this combination, developers don't need to maintain any web servers — they simply upload built frontend files to an S3 bucket and distribute them via CloudFront for globally accelerated access. This architecture typically costs just a few dollars per month, making it extremely cost-effective for personal projects or MVP validation.
The backend uses a Lambda + API Gateway serverless combo to provide the inference endpoint. AWS Lambda is an event-driven compute service where developers upload function code, and Lambda automatically spins up containers to execute the code when requests arrive, billing based on actual invocation count and execution duration. API Gateway serves as the HTTP entry point, handling routing, authentication, and traffic control. Together, they enable building RESTful APIs without managing any servers. However, Lambda has some hard constraints: deployment package size is capped at 250MB (uncompressed), maximum memory is 10GB, and maximum execution time is 15 minutes. For ML inference scenarios, model file size and loading time often become bottlenecks — which is the root cause of the cold start issues encountered in this project.
The author admitted this was his first time using React and candidly said "every minute was painful" — a candid complaint that resonates with the universal experience of many backend engineers transitioning to full-stack development.
Worth noting is the trade-off around error handling. The author mentioned he hadn't yet mastered proper error throwing patterns in React, so he chose to "disable the button when inputs don't meet requirements." He acknowledged this might be bad practice in a production environment. This actually reflects a common engineering reality: during the MVP stage, defensive UI constraints are often easier to implement than comprehensive error handling, but it's certainly not a long-term solution. In mature React applications, Error Boundaries are typically used to catch rendering exceptions, combined with try-catch blocks and state management to display user-friendly error messages.
Data Pipeline and Automated Model Retraining
A highlight of the project is its automated data and model update mechanism. The author uses a Step Functions + Lambda + EventBridge combination to orchestrate the full workflow of data scraping, processing, and model retraining. AWS Step Functions is a visual workflow orchestration service that lets developers chain multiple Lambda functions, ECS tasks, and other AWS services into a directed acyclic graph (DAG), supporting conditional branching, parallel execution, error retries, and state passing. EventBridge (formerly CloudWatch Events) is an event bus service that can automatically trigger Step Functions workflows based on time schedules (e.g., Cron expressions) or external events. This combination is widely used in MLOps for building automated pipelines for scheduled data scraping, feature engineering, model training, and evaluation. Compared to traditional scheduling tools like Airflow, its advantage lies in being fully Serverless — no scheduler infrastructure to maintain. This orchestration allows the model to continuously ingest newly scraped data, forming the embryo of a "self-evolving" system.
For model management, the author chose MLflow to store and load model artifacts. MLflow is an open-source machine learning lifecycle management platform created by Databricks, comprising four core components: Tracking (recording experiment parameters, metrics, and outputs), Projects (reproducible run environment definitions), Models (unified model packaging and deployment format), and Model Registry (model version management and stage transitions). In this project, MLflow is primarily used to store trained model artifacts, including serialized model files, preprocessing pipelines, and metadata. To control costs, the author didn't use AWS-managed MLflow tracking services (such as SageMaker with MLflow, which charges by the hour), but instead self-hosted a persistent ECS service running the MLflow Tracking Server, reasoning that this was actually cheaper. An MLflow Tracking Server requires a persistent storage backend (typically S3) and a metadata database (such as PostgreSQL). While self-hosting requires some operational overhead, it's genuinely more economical for low-usage personal projects.
Lambda Cold Start: A Classic Pain Point of Serverless ML Inference
If there's one lesson from this project that deserves the most attention, it's the Lambda cold start problem.
The author encountered a particularly thorny dilemma: loading the model and artifacts from MLflow takes approximately 40 seconds, while API Gateway has a maximum timeout of 30 seconds. This means — the first invocation almost certainly fails. Users get an error on their first visit, and the service only works properly after Lambda has "warmed up."
Lambda cold start refers to the process where AWS must initialize an execution environment from scratch when no reusable one is available. This process includes: allocating compute resources, downloading the deployment package or container image, initializing the runtime environment (e.g., the Python interpreter), and executing initialization code (e.g., importing libraries and loading models). For lightweight APIs, cold starts typically complete within 100–500 milliseconds. But for ML inference scenarios, just loading scikit-learn, pandas, and similar libraries can take several seconds, and downloading model files from a remote source (like S3 or MLflow) can easily push total time past 30 seconds. API Gateway's default timeout cap is 29 seconds and cannot be adjusted — creating the fatal bottleneck seen in this project.
This is a classic pain point of Serverless architecture in ML inference scenarios. The industry typically has several solutions:
- Provisioned Concurrency: Keeps Lambda instances pre-warmed by maintaining a specified number of "warm" instances to eliminate cold starts. The trade-off is continuous billing, which can be expensive for personal projects with unstable traffic.
- Model Caching Optimization: Package model artifacts into a Lambda Layer (max 250MB) or container image (max 10GB) to avoid loading from remote sources at runtime. Deploying Lambda via container images is a newer approach that lets you bake model files directly into Docker images, which are cached in AWS infrastructure after the initial pull.
- Switch to Containerized Inference: Using persistent services like ECS/Fargate eliminates cold start issues, though at higher cost. Fargate is AWS's serverless container solution — no EC2 instance management required, but containers run continuously and bill by time.
- Asynchronous Invocation + Polling: Bypasses the API Gateway 30-second hard limit. The client receives a task ID immediately upon request, then polls a separate endpoint for results while Lambda executes inference asynchronously in the background (up to 15 minutes).
The author accurately identified the root cause — loading models from MLflow is the primary source of latency. A pragmatic improvement would be embedding the model directly into the deployment package to reduce runtime remote I/O.
Model Performance: The Dual Challenge of Class Imbalance and Data Noise
On the algorithmic side, this project also offers many thought-provoking observations.
Handling Class Imbalance
The model achieved an F1 score of 72%, with severe class imbalance in the data (89:11). The F1 score is the harmonic mean of Precision and Recall, ranging from 0 to 1. In class-imbalanced scenarios, it reflects a model's ability to identify the minority class far better than simple Accuracy — for example, in this project, even if the model predicted every sample as the majority class, accuracy would still reach 89%, but the F1 score would be very low.
The author tried both undersampling and oversampling, but neither worked. Undersampling reduces majority class samples to balance class counts; the simplest approach is randomly deleting majority class samples, with the downside of losing potentially useful information. Oversampling increases minority class samples to balance the distribution; common methods include simple duplication of minority samples and SMOTE (Synthetic Minority Over-sampling Technique, which generates synthetic samples by interpolating between minority class instances). In a severely imbalanced 89:11 scenario, undersampling discards approximately 88% of majority class data, causing significant information loss, while oversampling can lead to overfitting on minority class samples. When the dataset is small and labels contain noise, both methods often produce unsatisfying results because they only change the quantity distribution of samples without introducing new discriminative information.
His next planned step is to try Focal Loss — a loss function specifically designed for class imbalance, originally proposed by Kaiming He et al. in the 2017 paper Focal Loss for Dense Object Detection. Its core idea is to dynamically adjust the learning weight of each sample: when the model can already classify a sample correctly with high confidence, that sample's contribution to the total loss is significantly reduced; for hard-to-classify samples, the loss remains high. Unlike traditional resampling methods, Focal Loss doesn't alter the training data distribution but instead achieves dynamic attention allocation at the loss function level. It has been widely validated in fields like object detection and typically performs more stably in practice.
Regarding the failure of sampling methods, the author's assessment was rather blunt: "I think they were a waste of time all along." This view may be somewhat absolute, but it genuinely reflects a common sentiment in frontline practice — simple resampling rarely delivers stable improvements in many real-world scenarios, and improving the loss function or acquiring more real data is often a more fundamental solution.
"Marketing Noise" in Training Data
Even more interesting is a business-level insight: some brands deliberately label garments that don't actually require dry cleaning or hand washing as "dry clean only" or "hand wash only" to reinforce their premium positioning and justify higher prices.
This means the labels in the training data inherently contain "marketing noise" (label noise) — a problem that algorithms alone cannot solve. In machine learning theory, label noise is considered more destructive than feature noise because the model's learning objective is to fit the labels — if the labels themselves are wrong, the more precisely the model fits the training data, the more it's actually learning incorrect patterns. Common approaches for handling label noise include: manual review and data cleaning, using noise-robust loss functions (such as Symmetric Cross Entropy), or using methods like Confident Learning to automatically identify and remove suspicious labels. However, in this project, the noise originates from brands' subjective marketing strategies — even contacting the brands might not yield truthful care recommendations.
As the author lamented — "Real world data is humbling." This is a lesson every ML practitioner eventually learns: the ceiling of data quality often determines the ceiling of model performance.
Engineering Reflections: Choices and Compromises in Real Projects
What makes this project especially valuable is that the author candidly documented various compromises made during the engineering process:
- First time using React — painful but got it done;
- First time using Terraform — found it "boring" (since he was already familiar with AWS), but recognized the templates are reusable: "a win is a win";
- The commit history features classic debugging commits like "MULTIPLE 'fix' 'final fix' '.'" (something every developer can relate to);
- ECS services and task definitions were initially created manually in the console, and only later migrated to Terraform.
Finally, the author raised an excellent engineering question: should ECS resources already created in the console be retroactively added to Terraform files to make it easier for others to reproduce?
From an Infrastructure as Code (IaC) best practices perspective, the answer is clear — yes, they should be added. Terraform is an open-source IaC tool from HashiCorp that uses HCL (HashiCorp Configuration Language) to describe cloud resources, previewing changes with terraform plan and deploying with terraform apply. It maintains a state file to track the actual state of resources and compares it against the code definition on each execution. Bringing all infrastructure under Terraform management not only ensures environment reproducibility but also prevents "Configuration Drift" — the problem of manual console changes being inconsistent with code definitions. Configuration drift is a common operational hazard: when team members make emergency changes via the console and forget to sync them back to code, the next terraform apply could accidentally overwrite manual modifications or even cause production incidents. For resources already created manually, the terraform import command can be used to bring them under management. For an open-source project, complete IaC definitions dramatically lower the barrier for others to get started.
Conclusion: A Complete System Is More Valuable Than Perfect Metrics
This dry cleaning prediction model may not have a dazzling F1 score, and the website will only be briefly online (the author doesn't want to spend too much on AWS bills). But it's an extraordinarily authentic end-to-end ML engineering sample. Starting from a minor shopping annoyance, the author independently completed data scraping, model training, automated retraining orchestration, cloud deployment, and even frontend development — this kind of full-stack practice is exactly the path through which many AI engineers rapidly grow.
It reminds us: building a complete system that works end-to-end is often more valuable than chasing perfect metrics on any single component. And those pitfalls — cold start timeouts, class imbalance, data noise, manual configuration migration — are precisely the real-world challenges that textbooks rarely cover in detail, yet appear repeatedly in production.
Related articles

The Finn: An AI Agent Deployed on a Router That Won't Stop Complaining
The Finn is an open-source project that deploys a complaining AI agent on a router. We break down its edge AI deployment challenges, persona design philosophy, and what it means for local AI agents.

Behind OpenAI Cutting Off Cursor: The Ecosystem Power Play Triggered by Musk's Acquisition
After SpaceX acquired Cursor for $60B, OpenAI cut off GPT model access. A deep dive into the real reasons, Anthropic's dilemma, and the impact on developers.

GitHub Daily · August 31: Local AI Servers and Training LLMs from Scratch
GitHub Trending Aug 31: minimind trains a 64M-param LLM in 2 hours; ODS turns any PC into a local AI server; plus OSINT tools and game enhancers.