The most common mistake when building software that involves data is reaching for machine learning when a simpler solution exists. ML is powerful for specific problems, but it is also slow to build, requires significant data, fails in unpredictable ways, and is hard to debug. Before starting any ML project, the question to ask is: can I write a clear heuristic for this? If yes, write the heuristic first.
This post gives you a concrete decision framework for when to use ML and when not to, with real examples of problems that look like they need ML but do not.
The Core Question: Can You Write a Rule?
Machine learning learns rules from data. If you can write the rules yourself, you do not need ML.
This sounds obvious, but it is violated constantly in practice. Here are problems people frequently reach for ML to solve, along with the simpler solutions that actually work.
"Is this email from our domain?" This looks like a classification problem. It is a string check.
def is_company_email(email: str) -> bool:
return email.endswith("@yourcompany.com")
One line. Zero training data. Zero model maintenance. Zero latency. Works perfectly.
"Show me recent orders." This looks like a personalization or recommendation problem. It is a database query.
SELECT * FROM orders
WHERE user_id = $1
ORDER BY created_at DESC
LIMIT 20;
No ML, no embedding, no recommendation engine. Just a query sorted by date.
"Is this a valid phone number?" This looks like a validation problem that might need ML to handle international formats. It is a regex combined with a library.
import phonenumbers
def is_valid_phone(number: str, region: str = "US") -> bool:
try:
parsed = phonenumbers.parse(number, region)
return phonenumbers.is_valid_number(parsed)
except Exception:
return False
The phonenumbers library handles every country's format. No training data, no model, handles edge cases better than any ML approach.
"Classify this support ticket into: billing, technical issue, or feature request." This looks like an NLP classification problem. If the categories are broad and you have a few dozen keywords per category, a keyword-matching approach often works well enough.
BILLING_KEYWORDS = {"invoice", "charge", "payment", "refund", "billing", "subscription"}
TECHNICAL_KEYWORDS = {"error", "bug", "crash", "broken", "not working", "fails"}
FEATURE_KEYWORDS = {"feature", "request", "add", "would like", "suggestion", "idea"}
def classify_ticket(text: str) -> str:
text_lower = text.lower()
scores = {
"billing": sum(1 for kw in BILLING_KEYWORDS if kw in text_lower),
"technical": sum(1 for kw in TECHNICAL_KEYWORDS if kw in text_lower),
"feature": sum(1 for kw in FEATURE_KEYWORDS if kw in text_lower),
}
return max(scores, key=scores.get)
This is not perfect. ML classification would be more accurate on edge cases. But if 85% accuracy is sufficient for your use case, and you can build this in an hour versus an ML solution in a week, write this first. Measure the accuracy. Only upgrade to ML if the accuracy is actually insufficient.
The Decision Tree for Using ML
Work through this in order before starting any ML project:
1. Can you write an exact rule? String matching, regex, date comparison, threshold comparison. If yes, write the rule.
2. Can you write a heuristic that is good enough? Keyword scoring, weighted rules, decision trees you write by hand. If this meets your accuracy requirement, use it.
3. Is your problem actually about pattern recognition in unstructured data? Images, audio, natural language beyond simple classification, handwriting. If yes, ML is likely the right tool. If no, reconsider.
4. Do you have enough labeled data? As a rough guide: simple classification with few classes needs at minimum a few hundred labeled examples, ideally thousands. Complex tasks need tens of thousands. If you do not have data and it would take months to collect, ML may not be feasible.
5. Have you tried a pre-trained model or an LLM prompt first? For many NLP classification tasks, a simple GPT-4o prompt (classify this text into one of these categories) outperforms a custom-trained model and requires zero training data. Try the LLM approach before training a model.
Where ML Genuinely Helps
There are domains where no heuristic works and ML is the right answer.
Image and video understanding. Detecting objects in photos, recognizing faces, reading handwriting, classifying medical images. These tasks cannot be solved with rules because no one can write rules for "what makes a tumor look malignant in a CT scan." The patterns are too complex and too high-dimensional for manual rule definition.
Natural language understanding beyond classification. Answering questions about documents, summarizing text, translating between languages, extracting structured data from unstructured prose. These require understanding meaning, which is not reducible to keyword matching.
Personalization at scale. Recommending content or products to millions of users based on their individual behavior patterns. The number of rules required would be intractable; ML learns the patterns from behavioral data.
Anomaly detection in high-dimensional data. Finding unusual patterns in logs with hundreds of variables, detecting fraud in transaction sequences, flagging network intrusions. Rules break down when the number of variables is high and the patterns of normal versus anomalous behavior are complex.
Speech and audio. Transcribing speech to text, identifying speakers, detecting emotions in voice. Again: no rules can be written for these tasks at production quality.
The Cost of Getting It Wrong
The costs of using ML when you did not need to:
- Time: training and evaluating an ML model takes days to weeks. Writing a heuristic takes hours.
- Data: ML requires labeled training data. Getting labeled data requires either manual labeling (time and cost) or finding existing datasets.
- Maintenance: ML models degrade over time as data distributions shift. Rules can be updated in minutes. Retraining a model requires a full training pipeline.
- Debugging: when a rule-based system fails, you can see exactly why. When an ML model fails, the reason is often opaque.
- Infrastructure: deploying a model requires a serving layer, monitoring, versioning, and rollback capability. A rule is just code.
The engineer's heuristic: if you can solve the problem without ML, you should. ML is a powerful tool for problems that genuinely require it, but it is overengineering for problems that do not.
A Practical Example: Content Moderation
A common ML project: building a content moderation system to flag inappropriate user posts.
The ML approach: collect tens of thousands of labeled examples (appropriate vs. inappropriate), train a classifier, evaluate on held-out data, deploy, monitor for drift.
The simpler approach first: maintain a list of blocked terms and patterns. Block posts matching known hate speech phrases, profanity, and spam patterns. This handles 70 to 80% of cases with zero training data and same-day deployment.
The escalation path: use an LLM classifier for edge cases. Send borderline posts to GPT-4o or Claude with the prompt "Is this post appropriate for a professional community? Answer yes or no and explain why." This handles the nuanced cases that keyword matching misses without building a custom ML pipeline.
Use custom-trained ML only if the LLM approach is too slow or too expensive at your content volume, or if you need a model that is fine-tuned on your specific community's standards.
This is the general pattern: start with rules, escalate to LLM prompts, escalate to fine-tuned models only when necessary.
Keep Reading
- Neural Networks Explained: A Visual Guide for Software Developers — When you do need ML, start here
- RAG vs Fine-Tuning: Which One Does Your Application Actually Need? — The decision framework for LLM-specific choices
- How Software Developers Can Use LLMs Effectively in 2026 — How to use LLMs as a shortcut that avoids custom ML in many cases
Pristren builds AI-powered software for teams. Zlyqor is our all-in-one workspace — chat, projects, time tracking, AI meeting summaries, and invoicing — in one tool. Try it free.