Skip to main content

How Health Scores Help Developers Choose Better Packages

·PkgPulse Team

TL;DR

GitHub stars are vanity metrics. Health scores are actionable. A package with 50K GitHub stars might have 0 commits in 2 years, 200 open issues, and declining downloads. A package with 5K stars might have weekly releases, 10 active maintainers, and 2M weekly downloads. Health scores aggregate the signals that actually predict maintenance quality and longevity — so you make package decisions on data, not hype.

Key Takeaways

  • GitHub stars: correlation with quality = 0.2 — stars measure popularity at a point in time
  • Downloads + trend — the strongest signal of continued adoption
  • Last publish date — packages not updated in 18+ months carry risk
  • Issue velocity — fast issue response = active maintainer
  • TypeScript coverage — now a first-class quality signal
  • Dependency count — high transitive deps = higher attack surface + bundle size

Why GitHub Stars Mislead

Real examples of star count vs health disconnect:

Package A: 52,000 stars
  Last commit: 18 months ago
  Open issues: 847 (no responses for 6 months)
  Weekly downloads: 120K (declining 40% YoY)
  TypeScript support: None (@types/packageA missing)
  Verdict: DO NOT USE for new projects

Package B: 3,200 stars
  Last commit: 3 days ago
  Open issues: 12 (average response: 2 hours)
  Weekly downloads: 2.4M (growing 80% YoY)
  TypeScript support: Built-in, strict
  Verdict: Excellent choice

Stars reflect: discovery, viral blog posts, trending periods
Stars don't reflect: maintenance activity, community responsiveness, longevity

What Health Scores Measure

Dimension 1: Maintenance Activity

Signals:
- Days since last npm publish (lower = better)
- Commit frequency (average per month)
- Issue close rate (% of issues resolved in 30 days)
- PR merge rate and time

Scoring rubric:
Published < 30 days:     30/30 points
Published 30-90 days:    25/30
Published 90-365 days:   15/30
Published 1-2 years:     5/30
Published > 2 years:     0/30

Why this matters:
- Security vulnerabilities get patched
- Breaking changes in dependencies get fixed
- New Node.js/TypeScript versions get support

Dimension 2: Adoption and Growth

Signals:
- Weekly download count (absolute)
- Download trend (3-month and 12-month growth rate)
- Dependents count (packages that depend on it)

Why downloads beat stars:
- Stars can be bought/gamed (GitHub star purchasing is a real market)
- Downloads represent actual usage in CI/CD, not just bookmarks
- Download trend reveals momentum (growing = healthy ecosystem interest)
- Dependents count reveals lock-in to the ecosystem

Interpreting download trends:
+50%+ YoY: Rapidly growing, strong momentum
+10-50%:   Healthy growth
-10% to +10%: Stable
-10% to -30%: Slight decline — watch
-30%+ YoY:  Significant decline — evaluate alternatives

Dimension 3: TypeScript Support

Scoring levels (0-20 points):
20 pts: Written in TypeScript, types bundled
15 pts: Bundled .d.ts files (not written in TS but types included)
10 pts: DefinitelyTyped @types/ package available
5 pts:  Types available but outdated
0 pts:  No types, any usage everywhere

Why this matters in 2026:
- 83% of new projects use TypeScript
- Packages without types require manual type declarations
- Type accuracy predicts API correctness (if types are wrong, API docs often are too)

Dimension 4: Security Posture

Signals:
- Known CVE count (from npm audit database)
- Time to patch past CVEs
- Dependency count (attack surface)
- Package provenance (verified build chain)

Scoring:
0 known CVEs:        30/30
1-2 CVEs, patched:   20/30
1-2 CVEs, unpatched: 10/30
3+ CVEs:             0/30

Transitive dependency count:
< 5 deps:    20/20
5-20 deps:   15/20
20-50 deps:  10/20
50+ deps:    5/20

Dimension 5: Bundle Efficiency

Signals:
- Gzipped bundle size
- Tree-shaking support (sideEffects: false in package.json)
- ESM support (better tree-shaking for bundlers)
- Dependency weight (deps bundle size)

Scoring:
< 5KB gzip:    20/20
5-25KB:        15/20
25-100KB:      10/20
100-500KB:     5/20
> 500KB:       0/20

Real-World Health Score Examples

High Health Score (Drizzle ORM: 92/100)

Drizzle ORM health breakdown:
Maintenance:          29/30  (published 5 days ago)
Adoption:             25/25  (2M downloads, +400% YoY)
TypeScript:           20/20  (written in TypeScript, excellent inference)
Security:             28/30  (0 CVEs, 12 transitive deps)
Bundle efficiency:    17/20  (3KB runtime, ESM support)
Composite:            92/100

Interpretation: Excellent choice for new projects.
Active development, strong growth, TypeScript-first.

Declining Health Score (TypeORM: 52/100)

TypeORM health breakdown:
Maintenance:          15/30  (last published 4 months ago, slow issue response)
Adoption:             18/25  (3M downloads but -15% YoY)
TypeScript:           15/20  (TypeScript support but legacy decorator approach)
Security:             14/30  (2 unpatched moderate CVEs, high dep count)
Bundle efficiency:    10/20  (larger bundle, CJS-first)
Composite:            52/100

Interpretation: Still works, but declining. For new projects,
consider Prisma or Drizzle instead.

How to Read Health Scores in Context

Health scores are useful signals, not absolute verdicts:

High score but wrong choice:
- styled-components: 75/100 (active, popular) but RSC-incompatible
  → High health score, but wrong choice for Next.js 15 app router

Low score but acceptable:
- An internal analytics package: 40/100 (slow updates)
  → Slow updates are fine if the API is stable and you don't need new features

Score trajectories matter:
- Package at 80/100 but declining 5 points/quarter → better alternatives exist
- Package at 60/100 but improving rapidly → promising, monitor it

Building Your Own Package Evaluation Process

# 5-minute package evaluation checklist:

1. Check PkgPulse health score
   → pkgpulse.com/compare/[package-a]-vs-[package-b]

2. Check download trend
   → npmtrends.com for 12-month view

3. Check last publish date
   → npm view [package] time.modified

4. Check TypeScript support
   → npmjs.com/package/[package] → sidebar shows "TypeScript"

5. Check bundle size
   → bundlephobia.com/package/[package]

6. Scan GitHub issues
   → Filter by "no response" label — are issues being ignored?

7. Check dependents
   → npmjs.com/package/[package] → "Used by N packages"
   → High dependents = slower to abandon

# Total time: 5-10 minutes
# Catches 90% of bad package choices

See detailed health scores and download trends for any npm package comparison on PkgPulse.

See the live comparison

View react vs. vue on PkgPulse →

Comments

Stay Updated

Get the latest package insights, npm trends, and tooling tips delivered to your inbox.