Video summary

Dependency Cultures - Richard Feldman | SSW 2026

Main summary

Key takeaways

Technology

Tech Summary of the Talk: “Dependency Cultures” (Richard Feldman, SSW 2026)

1) Evolution of web stacks: fewer “carefully chosen” deps vs more layered abstractions

Feldman contrasts early web startups (mid/late 1990s) with modern stacks.

  • Early example stack (late 1990s / early 2000s vibe): Debian on physical servers, Apache + Perl, a forked MW forum for auth, Postgres, memcached, SMTP via sendmail, JavaScript/jQuery, and jQuery UI widgets.
  • He also points out how VIAweb used bare metal, FreeBSD, Common Lisp, and C for performance.

Modern stacks tend to follow a layered abstraction pattern, which increases dependency counts:

  • serverless/VM abstractions (e.g., Firecracker / AWS Lambda)
  • layered platform tooling (e.g., Vercel)
  • type/runtime layers (e.g., TypeScript on Node.js, Next.js)
  • ORM/data layers (e.g., Prisma, Neon as distributed Postgres abstraction, Upstash abstractions)
  • storage/CDN (e.g., S3, CloudFront)
  • UI/tooling (e.g., Tailwind, React, shadcn/ui)
  • “mixing client and server state” (referencing a prior talk)

Key theme: modern dependency sets often arise from ecosystem norms and layering—not from proving a stack is the “best possible” technical choice.


2) Main argument: dependency count is mostly cultural, not technical necessity

Feldman argues you can build similar products with drastically different dependency graph sizes, and the difference reflects ecosystem conventions more than technical requirements.

Websites comparison (2026): same job, wildly different dependency graphs

He compares dependency graphs for sites that provide programming-language docs/tutorials and an interactive “run code” experience for:

  • TypeScript, Node.js, Python, Ruby, Rust, Zig, Go, Rock

Even though the sites share a similar purpose, dependency counts vary dramatically:

  • one site has ~0 direct/visible dependencies
  • another has ~1,800 dependencies (mostly indirect)

A key puzzle: which sites run a compiler in-browser?

  • TypeScript and Rock.

Insight: you don’t need huge dependency graphs to compile/run code in the client.

For TypeScript’s large graph, Feldman identifies Gatsby (a React framework) as a major contributor pulling in many indirect dependencies. So the documentation/interactive experience doesn’t require those dependencies—the culture/ecosystem defaults do.

Games comparison: remakes share patterns, ecosystems differ

He repeats the dependency-graph exercise for nine games (open-source / source-available where dependency inspection is possible). He then looks at which games are remakes and compares their dependency-graph “shape.”

Examining ecosystem differences across Rust, C#, and C++ (remakes within those ecosystems):

  • npm-like ecosystems tend to have many direct and many indirect dependencies
  • C++ gamedev is the opposite: very few direct deps and typically almost no indirect deps

Explanation of the C++ approach: dependencies are often vendored (checked in / copied into the repo) rather than pulled via a package manager that creates deep transitive dependency trees.

He also references Jonathan Blow, who suggests vendored dependencies should simply be present in the checkout for reliability (e.g., “desert island” no-internet builds).


3) Security analysis: “More dependencies → more attack vectors”

Feldman ties dependency graph size to:

  • supply-chain risk
  • update/remediation risk

“Dependency or no” anecdote (malicious indirect dependency)

A developer adds a small missing function by copying a few lines. Later, upstream releases a “flatmap” package that becomes a dependency.

  • A later repo issue finds a backdoor dependency:
    • a malicious actor released a patch that steals crypto during an upgrade.
  • The repository is archived because people stop trusting it.

Point: even “small” fixes can grow into indirect dependencies over time, multiplying risk.

Dependabot critique

Dependabot-style automation is often positioned as:

  • easy updates

But Feldman frames updates as double-edged:

  • updates can fix bugs
  • updates can also introduce malware/bugs

He argues for something closer to Mitchell Hashimoto–style vetting rather than always updating.

Log4Shell example (latent bug, not necessarily malicious)

He cites Log4Shell / log4j-like vulnerabilities:

  • a newly introduced feature created an unanticipated vulnerability
  • many organizations updated eventually, but indirect dependencies can delay patch propagation

Key claim: with lots of indirect dependencies, updating direct dependencies may still leave you exposed through transitive dependencies that haven’t been updated.

Overall conclusion on risk

He cites growth in malicious package incidents (including “hundreds of thousands” malicious packages in 2024). Therefore, dependency sprawl increases exposure to:

  • direct malicious compromises (active supply-chain attacks)
  • indirect latent vulnerabilities that take longer to remediate

Soundbite: “Mo dependencies, mo problems.”


4) Concrete engineering case study: Rock website aims for near-zero JS deps

Feldman describes what he did building the Rock language website.

  • The Rock compiler runs in WebAssembly, with the compiler written in Zig—avoiding the need for a JS compiler dependency.
  • The main remaining need is syntax highlighting as users type code in the browser.

He tried npm first, but found highlight.js:

  • “internet’s favorite JavaScript syntax highlighter”
  • huge coverage (192 languages, 512 themes)

Feldman argues highlight.js is overkill and mismatched because it relies on:

  • regex-based custom language definitions

Yet real language features (e.g., string interpolation, nesting, non-regular constructs) don’t map cleanly to regex.

Instead, he:

  • ported tokenizer logic from Zig to JavaScript
  • reused only theming/coloring
  • achieved ~6 KB versus highlight.js at ~9 KB compressed (and larger with language bundles)
  • gained faster performance and better correctness/edge-case handling (avoiding regex fragility)

Broader takeaway: there’s a spectrum beyond “always grab from the shelf”:

  • copy/paste + attribution
  • fork/trim like HashiCorp
  • implement directly for correctness and reduced dependency graph size

5) Prescriptive recommendations implied by the talk

  • Prefer fewer dependencies when feasible.
  • Don’t treat “update constantly” as the default:
    • emulate HashiCorp-style thinking: trim unused parts, don’t upgrade unless needed, and be selective about risk/benefit.
  • If you only need a tiny utility (e.g., a “4-line function”):
    • copy it (with appropriate attribution/license) rather than adding an indirect dependency.

Main Speakers / Sources (explicitly mentioned)

  • Richard Feldman (main speaker)
  • Mitchell Hashimoto / HashiCorp (dependency philosophy examples: trim dependencies; upgrade only intentionally)
  • Russ Cox (mentioned as someone to hear about a related packaging topic)
  • Andrew Kelly (mentioned as asking about dependency practices; later referenced as a take/interview source)
  • Jonathan Blow (advocates vendoring dependencies in source control; referenced via Software Unscripted)
  • Biggie Smalls (“Mo dependencies, mo problems”), used as a concluding motif)

Supply-chain examples referenced

  • npm leftpad
  • event-stream / flatmap stream backdoor dependency
  • Log4Shell / log4j

Original video