1. Introduction
Determining whether a technology is "dead" requires moving beyond subjective developer opinions, Reddit flamewars, and Hacker News echo chambers into empirical data analysis. Our engine aggregates multiple signals to compute a unified score so you don't have to rely on that one guy who says "X is dying" every week.
2. Data Sources
- GitHub Activity: Stars, forks, commit frequency, and issue resolution time (or lack thereof).
- NPM Registry: Weekly download velocity and dependency inclusion rates.
- StackOverflow: Question volume and answer latency (the "despair index").
3. The Deaditude Formula
The core equation relies on a weighted average of normalized metric decay over time. Given a time $t$, the Deaditude $D(t)$ is expressed as:
Where:
$G_v$ = Normalized GitHub Velocity
$N_v$ = Normalized NPM Velocity
$S_v$ = StackOverflow Despair Index (Unanswered Questions)
3.1 Mathematical Implementation (Code snippet)
In practice, our Python-based calculation engine adjusts these weights dynamically based on the age of the technology and normalises the variance based on data quality:
def calculate_deaditude_score(
metrics: Dict[str, Dict[str, float]],
tech_info: Optional[Dict[str, Any]] = None,
) -> Dict[str, Any]:
tech_age = _get_tech_age(tech_info)
weights = YOUNG_TECH_WEIGHTS if tech_age <= YOUNG_TECH_THRESHOLD else BASE_WEIGHTS
eff_w: Dict[str, float] = {}
sigmas: Dict[str, float] = {}
explanations: list[str] = []
# Effective weights & per-source σ
for src, base_w in weights.items():
m = metrics.get(src) or {}
q = _quality(m)
eff_w[src] = base_w * q
sigmas[src] = _sigma_for_quality(q)
# Renormalise
total_w = sum(eff_w.values()) or 1.0
for src in eff_w:
eff_w[src] /= total_w
# Weighted mean (0-10)
overall = sum(
eff_w[s] * metrics.get(s, {}).get("deaditude_score", 5.0)
for s in eff_w
)
adjusted_overall = _adjust_score_by_age(overall, tech_age)
# ... calculates Confidence Interval and returns 0-100 score
pct = adjusted_overall * 10
return { "overall_score": round(pct, 1) }3.2 Data Collection Example (GitHub)
We query the GitHub GraphQL API to fetch exact, high-fidelity metrics, defaulting gracefully to REST when rate limited:
def _calculate_deaditude(metrics: Dict[str, Any]) -> float:
score = BASE_SCORE # Starts at neutral 5.0
# Negative signals (penalize inactivity)
commits_30d = metrics.get("commits_last_30d") or 0
if commits_30d == COMMITS_NONE_THRESHOLD:
score += COMMITS_NONE_PENALTY
elif commits_30d < COMMITS_LOW_THRESHOLD:
score += COMMITS_LOW_PENALTY
pr_age = metrics.get("pr_age_metrics", {}).get("avg", 0) or 0
if pr_age > PR_OLD_THRESHOLD:
score += PR_OLD_PENALTY
# Positive signals (reward popularity)
stars = metrics.get("stars", 0)
if stars > STARS_VERY_HIGH_THRESHOLD:
score -= STARS_VERY_HIGH_BONUS
return max(0, min(10, score))4. Peer Review
All data points and snapshots are stored in our open-source repository and are subject to public scrutiny. Re-evaluations occur on a bi-weekly basis.