Skip to content
DevMeme
3194 of 7435
The Infinite Proliferation of Competing Open Source Standards
OpenSource Post #3515, on Aug 7, 2021 in TG

The Infinite Proliferation of Competing Open Source Standards

Why is this OpenSource meme funny?

Level 1: Here We Go Again

Imagine you and your friends all have slightly different ideas for a game to play. One friend says, "Let's play tag, but with a twist I invented." Another friend says, "I have a different version of tag that's faster!" A third friend goes, "Well, in my tag you can tag everyone at once." Now you have three versions of essentially the same game, and it's getting confusing. So someone new comes along and insists, "This is silly, let's make one game that everyone will love, combining the best of all of these." But instead of actually uniting everyone, it just becomes a fourth slightly-different game of tag. In the end, you have even more games than you started with, and everyone is more confused than ever.

The feeling here is both funny and frustrating: every time someone tries to fix the problem of "too many choices," they end up creating one more choice. It's like having five flavors of ice cream and saying, "None of these are perfect, so I'll mix them all to make a new flavor everyone will prefer!" – and now it's just a sixth flavor on the menu. This meme is laughing at that never-ending cycle. Each new EventEmitter library was supposed to be the ultimate solution, but all it did was add to the pile. It's a bit like a cartoon where a character keeps trying to clean a mess but each attempt makes the mess bigger. You can't help but chuckle and think, "Here we go again – another 'solution' that only makes things more complicated!"

Level 2: Dependency Chain Reaction

Let’s break down what's happening in this meme step by step. The images show a series of NPM package pages for libraries named EventEmitter3, eventemitter4, EventEmitter5, EventEmitter6, and a mention of EventEmitter7. To understand this, first we need to know what an EventEmitter is and how NPM and package dependencies work in JavaScript.

  • EventEmitter (the original): In Node.js (a JavaScript runtime for server-side programming), an EventEmitter is a fundamental construct that allows different parts of code to communicate using events. Think of it like a messenger: one part of your program emits (sends out) an event, and other parts listen for those events and respond when they occur. Node.js provides a built-in EventEmitter class (in the core 'events' module) for this purpose. It's used heavily in Node's own APIs – for example, a network socket in Node is an EventEmitter that emits events like "data" (when new data arrives) or "error".

  • NPM (Node Package Manager): NPM is the package management system that comes with Node.js. It lets developers share and reuse code. You can install a library (package) by running npm install <package-name> and NPM will download that package (and whatever other packages it depends on). This way, developers often build applications by stitching together many small packages from the community. Each package usually focuses on one thing (which is great for reusability). But it also means for any given problem, you might find multiple packages offering similar functionality, and sometimes they even depend on each other. This can lead to a dependency chain: package A depends on B, which depends on C, and so on. Too long a chain or too many packages, and it can feel like a convoluted tangle – that's the concept of Dependency Hell (when managing and understanding all those interlinked pieces becomes very challenging).

Now, what about EventEmitter2, 3, 4, 5, 6...? These are all names of different NPM packages, created by different people over time, each one being an implementation (or extension) of the EventEmitter idea. Since the original EventEmitter is part of Node itself, why would anyone make a new one? Well, developers often have ideas to improve things: maybe add features, or make it run faster, or design it differently. They can't easily replace Node's built-in EventEmitter (that's tied to Node's releases), so they create their own versions and publish them on NPM for others to use as an alternative.

Here's the chain of events (pun intended) as reflected in the meme:

  1. EventEmitter2 – This was a real library created as an improved version of Node's EventEmitter. It added features like wildcard event names (listen to all events matching a pattern) and other enhancements, and it could handle more listeners without performance issues. The name EventEmitter2 implies it's "Version 2" or a successor to the original. This naming by number is a bit unusual (normally a library would just bump its internal version number), but since "EventEmitter" (no number) was already the name of the Node core thing, the author chose EventEmitter2 as the package name. This is a form of versioning through naming.

  2. EventEmitter3 – The meme starts with EventEmitter3, so presumably someone else (or later on) made yet another event emitter library. The screenshot banner says: "EventEmitter3 – Because there's also a number 2. And we're faster." This indicates the author of EventEmitter3 created it largely because EventEmitter2 existed. It's like they're saying: "Well, there's an EventEmitter2 out there already, so here's EventEmitter number 3, and hey, it's faster than the last one!" Speed and performance can be a selling point; perhaps this version optimized certain operations. The tone is slightly tongue-in-cheek in that tagline, but also real – performance was likely a key goal. So, EventEmitter3 is essentially another alternative, boasting improvements over 2. It likely has a similar API (so it can be used in place of 2 or the original) but is a separate package on NPM.

  3. eventemitter4 – Now another developer comes with EventEmitter4. The meme shows part of its README, where there's a section "9.6. Why not EventEmitter3". It explains: "EventEmitter3 does not have an onAny() function. The module is not implemented using any form of set algebra either. Therefore, I did not particularly feel like extending it." In simpler terms, the author of 4 had two main issues with EventEmitter3: it lacked an onAny() feature, and the way it was implemented internally (no "set algebra" – this might refer to how it manages sets of listeners) didn't suit them, making it hard to extend or improve. The onAny() feature probably means the ability to listen for any event on that emitter with one handler (catch-all for events). EventEmitter3 didn't support that, and the author wanted it. Instead of convincing the EventEmitter3 maintainer to add onAny() or changing their coding approach, they went ahead and made eventemitter4. They even named it all lowercase on NPM (eventemitter4), but in the docs refer to it as EventEmitter4. This is a new package again. At this point, we have four implementations (counting Node's original as the first). Each exists on NPM for anyone to install, which means if you’re a developer looking for an event emitter library, you have to choose: use the built-in one, or 2, or 3, or 4 – each with slightly different features or performance profiles.

  4. eventemitter5 – Yet another developer got involved. By the time we have EventEmitter5, you can sense the exasperation. The excerpt says: "Because there is an EventEmitter, EventEmitter2, EventEmitter3 and EventEmitter4. Let’s end the insanity and work together to fix the existing EventEmitter projects." So the EventEmitter5 author is basically saying, "Enough! This is crazy to have so many. Let's consolidate our efforts." The intention here is noble: they created EventEmitter5 perhaps as a rallying point for everyone to stop fragmenting and come together. Maybe it was intended to be backward compatible or to include all the good parts of earlier versions so everyone could adopt it going forward. They literally call out all previous ones in the README and plead to end the madness. However, the very act of releasing eventemitter5 means there's now one more library in the mix. If not all authors and users agree to jump to 5, it just becomes the fifth option. So even though the motivation was to unify, it somewhat backfired by adding yet another alternative. (This is exactly like saying "there are too many standards, I'll make a new standard to unify them" – and then you have one more standard.)

  5. eventemitter6 – At this point, things go from well-meaning to outright satirical. EventEmitter6's page (version 1.0.1, published 2 years ago relative to the meme's date) shows it has 5 dependencies – which are listed as EventEmitter, eventemitter2, eventemitter3, eventemitter4, eventemitter5. Yes, EventEmitter6 depends on all the previous ones! The README snippet reads: "That's a hell lot of them, and because there is no setMaxEventEmitterPkg, let's make EventEmitter great again! And we will make listeners pay for it!" This is presumably a joke by the author of 6. They acknowledge "that's a lot of them" (so many EventEmitters), then make a pun – "no setMaxEventEmitterPkg" refers to a property in Node's EventEmitter called setMaxListeners (which lets you increase the default limit on how many listeners you can add before it warns you). By saying no one set a max limit on number of EventEmitter packages, they're joking that the number of different EventEmitter libraries has grown uncontrolled. "Let's make EventEmitter great again!" mimics a political slogan, implying they're going to restore order or quality, and "we will make listeners pay for it!" is a humorous non-sequitur (mixing programming listeners with that slogan style). In practice, what EventEmitter6 did (depending on all previous ones) is very unusual. It might combine all features by internally using each one for different tasks, or more likely, it's a parody and doesn't truly solve anything – it's just making fun of the scenario. Technically, if you install eventemitter6, NPM will also install five other packages (1,2,3,4,5 as listed). So your project now has every variant included – perhaps the ultimate bloat for solving a simple problem! It's like a mega-all-in-one approach, which is the opposite of the single responsibility principle that tiny NPM packages usually adhere to. This is why we call it a dependency chain reaction – each new package pulls in the old ones, creating a long chain. If any one of those earlier packages has an issue, it trickles down into EventEmitter6. The meme exaggerates this to highlight how absurd things can become.

  6. EventEmitter 7 – Finally, the meme shows a card for EventEmitter7 with just a skull emoji 💀 and the words "We need to go deeper." This likely isn't a real package (or if someone published it as a joke, it might not have any real code). The phrase "We need to go deeper" is a reference to a popular meme from the movie Inception, where characters talk about going deeper into layers of dreams. Here it's applied to the layers of packages – as if saying, we can still add another layer to this craziness. The skull emoji signals that this is kinda "deadly" or the point of no return for sanity. It's basically poking fun at the idea that someone would be outrageous enough to actually make an EventEmitter7. It’s the meme's punchline: how deep does the rabbit hole go?

Throughout this chain, a few key concepts are at play:

  • Naming and Versioning: Normally, libraries use Semantic Versioning (semver) to indicate new versions: e.g., 2.0.0 -> 3.0.0 for big changes. Here instead, each author chose a new name with a number. This is partly because they weren't maintainers of the previous package, and partly to signal "this is a different project." But it means "EventEmitter5" isn't version 5 of one project, it's an entirely separate project that happens to come fifth in a sequence of similar tools. This is confusing for newcomers! It's a bit of a naming hack. It also reflects the challenge of NamingThings: all these packages do basically the same thing, so how to name them distinctly? Just number them like movie sequels. (Imagine if every time a new chef made a slight variation of a recipe, they named it "Spaghetti 2", "Spaghetti 3" and so on... it would be silly, right?)

  • Dependencies: A dependency means one piece of software relies on another to work. In NPM, when package A lists package B in its "dependencies", B will be installed as a sub-module of A. If EventEmitter6 has 5 dependencies (the other emitters), it means to use EventEmitter6, you implicitly also have all those others in your project. Each dependency can in turn have its own further dependencies. This can lead to a large dependency tree (or graph). NPM handles installing these for you automatically, but you as a developer might not even realize how many packages came along for the ride. The meme is highlighting a kind of absurd dependency inclusion: pulling in five alternatives that arguably do the same thing. It's like a greatest hits compilation album that just bundles the work of five different bands who all played the same song in slightly different ways.

  • JavaScript and Tiny Packages: The JavaScript ecosystem, especially around 2015-2017, became notorious for having a package for everything – even very trivial utilities. This has pros and cons. On one hand, why write code from scratch if a package exists? You can just import it. On the other hand, you might end up relying on a lot of external code for simple tasks (like the infamous left-pad package which was 11 lines to pad a string, yet when it was removed from NPM, it broke thousands of projects). The EventEmitter saga here is a commentary on that culture. An EventEmitter could be (and is, in Node) implemented in maybe ~100 lines of code. But we have multiple versions of that 100 lines as separate packages. And one package that includes all those versions together! It's both comedic and a bit eye-opening for a junior developer: just because something is on NPM doesn't automatically mean it's the best or only solution. Sometimes there are many options because of people not coordinating or wanting different things.

  • “Competing standards” joke: The text in the post caption about a universal standard references a known joke: often attributed to an XKCD comic strip. The idea is: when there's fragmentation (too many standards or tools), someone ambitious says "I'll create one standard that supersedes all of these." But inevitably, not everyone adopts the new one, so it just becomes one more standard among the rest, increasing the total count. In our case, EventEmitter5 attempted to be that unifier; it literally says "end the insanity." But unless everyone abandoned 2,3,4 to move to 5, it simply added to the pack. This teaches an important lesson in tech: newer isn't automatically universally adopted. Getting everyone to agree on one solution is as much a social challenge as a technical one.

In summary, the meme's content shows a chain reaction of NPM packages where each new package is responding to the existence of the previous ones. For a junior developer, it’s a humorous introduction to the realities of package management and community-driven development: you will encounter multiple libraries that do very similar things, and understanding the subtle differences (or why they exist) can be confusing. It’s also a cautionary tale: whenever you feel inclined to create "the next best version" of something, remember you might just be lengthening a chain. Maybe sometimes it's better to contribute to an existing project than to create a new competing one – or you could end up featured in a meme like this!

Level 3: One More Library

This meme lands a direct hit on the Dependency Hell culture of Node.js and NPM Packages. It highlights how JavaScript developers sometimes solve problems by adding another library rather than improving an existing one. The centerpiece is the absurd lineage of EventEmitter libraries, each with a version number in its name. The humor comes from the fact that there’s already a built-in EventEmitter in Node.js (no number), and even an EventEmitter2 that extended it – yet developers kept creating EventEmitter3, 4, 5, 6, and even a joke 7. It's a satirical exaggeration of real-life package proliferation. Experienced devs see this and groan-laugh because they've lived through similar scenarios: five different libraries for the same job, each author convinced their tweak warrants a new publish.

Why is this funny? Because it's painfully true. The meme is effectively quoting the well-known trope: "We have too many competing standards, let's make one universal standard... now we have one more standard." In the screenshots, each successive package justifies its existence in a comically self-important way:

  • EventEmitter3 boasts, "Because there's also a number 2. And we're faster." – implying it was created purely to outdo EventEmitter2 in performance. Classic developer pride: low latency and benchmarks as a selling point for a tiny library that most of us would consider already fast enough.
  • EventEmitter4 comes along and asks, "Why not EventEmitter3?" in its README, citing a missing feature (onAny() function) and some disapproval of EventEmitter3's internal design (no set algebra, whatever that means). Instead of contributing a patch to EventEmitter3, this author decided to roll their own. This is a prime example of the “Not Invented Here” syndrome – if a tool doesn’t fit my exact needs or style, I'll make a new one.
  • EventEmitter5 literally says, "Let's end the insanity and work together to fix the existing EventEmitter projects." – a plea for unity. It's trying to be the peacemaker, acknowledging the madness of four different emitters. Ironically, creating EventEmitter5 is itself adding to the insanity. The author basically went, "All right guys, too many choices, I'll publish one more choice to unite them all!" Senior devs recognize this well-meaning but counterproductive pattern: the one library to rule them all that... just becomes another library.
  • EventEmitter6 goes completely off the rails. Its description riffs on a political slogan: "Let's make EventEmitter great again! And we will make listeners pay for it!" – a cheeky nod to populist promises. Technically, what did the author of 6 do? They depended on all previous packages. The dependency list shows it literally pulls in EventEmitter, eventemitter2, eventemitter3, eventemitter4, and eventemitter5 as sub-dependencies. It's presumably trying to combine every feature and quirk from all prior implementations into a monstrous uber-package. This is dependency hell humor in a nutshell: instead of reducing complexity, EventEmitter6 has embraced all the complexity (five layers of it!). A seasoned engineer sees that and chuckles darkly – it's an absurd "if you can't beat 'em, join 'em (all at once)" approach. Also, any time you see a long chain of dependencies for something trivial, you think: this is brittle. One update or removal (remember the infamous left-pad incident?) and the whole tower might collapse.
  • Finally, EventEmitter7 is presented just as a title with a 💀 skull emoji and the ominous line, "We need to go deeper." This is pure meme-ing at this point, referencing the Inception film line to indicate an absurd depth of recursion. EventEmitter7 likely doesn't even exist for real – it's the hypothetical next step into madness. The skull emoji drives home that this is a dead end (or death wish) to continue this chain. It's as if the community’s collective sanity has died by the time we hit EventEmitter7.

For veteran devs, this progression is hilarious because it rings true beyond just this one case. It satirizes how the JavaScript ecosystem (in particular) ended up with countless tiny packages and much naming chaos. There's a famous saying: "There are two hard things in Computer Science: cache invalidation, naming things, and off-by-one errors." Here we've literally got namingthings and off-by-one combined: they solved naming by just incrementing a number in the name! No one could think of a unique brand for their emitter, so we got a sequence of numbered packages. And each time, the version number in the name effectively bypasses normal semantic versioning. Typically, version 3.0.0 of a library would be an update of 2.x.x. But on NPM, if you're a different author or you want to start fresh without the baggage, you can't publish to someone else’s project. So you make a new package and slap the next integer on the name itself, circumventing the usual versioning system. It's both clever and ridiculous – an unofficial convention for "forked but improved" libraries.

This exposes a real tension in open source: collaborating on a single project vs. splintering into many. The NodeJS community benefits from NPM's easy sharing (just npm publish and the world can use your code), but this also leads to duplication and fragmentation. The meme exaggerates it to a comical extreme: six different implementations of an event emitter pattern, plus a pseudo-seventh. Seasoned devs have felt this frustration when they search for a package – finding five options that all do almost the same thing, each with its own quirks and loyal supporters. It becomes a headache deciding which "standard" to go with, and there's that cynical voice saying "great, yet another one."

The post's caption about "one more competing standard" nails this perfectly. It's referencing that classic irony where the attempt to make one size fits all results in even more fragmentation. Every experienced developer has seen committees or teams try to create "The Ultimate Framework" or "the unified API" – and more often than not, it ends up as just another entry on the long list of choices. This is exactly why the meme elicits a knowing laugh (or groan). Package Management in JavaScript has a wild-west element: low barrier to create new packages means you get a thousand flavors of doing anything, from left-padding a string to implementing events. The tag DependencyHell usually describes the scenario when an application pulls in so many dependencies that managing them (updates, conflicts, security issues) becomes a nightmare. Here it's depicted more as the conceptual hell of too many redundant choices. Either way, the experienced perspective is: this is funny because it's true. We’ve all been there, shaking our heads at an endless chain of libraries leapfrogging each other.

In summary, the senior dev takeaway is a mix of amusement and weary resignation. The meme cleverly distills a tribal knowledge of software development: that trying to simplify the ecosystem can sometimes complicate it even more. It's a shared joke about our industry’s propensity to re-invent solutions ad infinitum. As a wise old programmer might say with a smirk, "Ah, yes, the elusive Universal Solution… guaranteed to spawn at least one more solution!"

Level 4: The Standardization Paradox

At the deepest level, this meme pokes fun at a fundamental paradox in tech culture: efforts to create one universal solution often just add yet another solution. It's a fractal of competing standards – an infinite regression where each attempt to consolidate spawns a new variant. In theoretical terms, it's reminiscent of a coordination failure or a game-theory scenario: without a central authority or consensus mechanism, individual developers keep reinventing the wheel in slight variations. There's even a famous law (jokingly) in our field: for every standard, there exists an equal and opposite alternative standard. Each library here (EventEmitter2, EventEmitter3, ..., EventEmitter6) is essentially a new "standard" for doing the same thing, created because the author couldn't align with the previous ones. The result is an unbounded sequence of packages – a countable infinity of EventEmitters, if you will, limited only by patience or humor.

In fact, the meme explicitly echoes the classic XKCD comic about standards proliferation. In a tongue-in-cheek formula:

$$ \text{NewStandardCount} = \text{ExistingStandardCount} + 1 $$

No matter how many packages already exist, someone will declare "let's unify everyone under one best library!" – and thus publish one more package. It's practically a law of nature in software. We see parallels in formal standards wars throughout computing history (think of XML vs JSON vs YAML, or the many JS frameworks): the One True Solution never remains the only one for long. This endless loop of one-upmanship also brings to mind Inception's "we need to go deeper" meme – each level down is just another dream within a dream, or in our case, another package within a package. The humor here is deeply rooted in this inevitable pattern: the harder we try for a final, unified fix, the more complexity and fragmentation we create. It's both absurd and almost cosmically inevitable, a Standardization Paradox that seasoned developers recognize all too well.

Description

This meme is a composite of screenshots from a package manager's website, likely npm, showcasing the absurd proliferation of libraries all attempting to solve the same problem. It follows the lineage of 'EventEmitter' packages from version 3 to 7. 'EventEmitter3' claims it's faster than version 2. 'EventEmitter4' was created because the author 'did not particularly feel like extending' version 3. 'EventEmitter5' ironically aims to 'end the insanity and work together to fix the existing projects.' By 'EventEmitter6,' the creator acknowledges 'That's a hell lot of them' and aims to 'make EventEmitter great again.' The sequence culminates with 'EventEmitter7,' which features a screaming face emoji and the caption 'We need to go deeper.' This perfectly illustrates the classic XKCD comic #927 about competing standards: the attempt to create a single unifying standard often results in just one more competing standard. For senior developers, this is a painfully familiar satire of open-source fragmentation, NIH (Not Invented Here) syndrome, and the perpetual, often futile, quest for a definitive solution

Comments

17
Anonymous ★ Top Pick We had 14 competing standards for event emitters. Now we have 15, and the latest one is a unifying framework written in Rust that compiles to WASM and requires a Kubernetes operator to manage its sidecar
  1. Anonymous ★ Top Pick

    We had 14 competing standards for event emitters. Now we have 15, and the latest one is a unifying framework written in Rust that compiles to WASM and requires a Kubernetes operator to manage its sidecar

  2. Anonymous

    npm’s consensus algorithm is simple: disagree with the maintainer, increment the integer, publish “EventEmitter-N,” and call that a major version - Byzantine fault tolerance via namespace clutter

  3. Anonymous

    Somewhere out there, a senior architect is explaining to their team why they chose EventEmitter4 over EventEmitter3 in a critical production system, while secretly praying nobody discovers EventEmitter8 was released last week with breaking changes that fix the exact bug they've been working around for six months

  4. Anonymous

    This is the JavaScript ecosystem's version of the XKCD 927 'Standards' comic, but with more npm install commands. EventEmitter5 tried to be the hero we needed, calling for unity with zero dependencies - only for EventEmitter6 to immediately undermine it by depending on ALL previous versions, complete with a 'make EventEmitter great again' promise and a threat to make listeners pay for it. Then EventEmitter7 shows up with 'we need to go deeper,' proving that in the NPM ecosystem, the only constant is that someone will always fork your fork. It's like watching a recursive function without a base case - eventually you'll hit a stack overflow, but the journey there is darkly hilarious. The real kicker? Somewhere, a junior dev is trying to figure out which one to use while a senior architect is having flashbacks to the left-pad incident

  5. Anonymous

    At this point, npm i eventemitter6 is a consensus algorithm - it depends on 1 - 5 until it reaches quorum

  6. Anonymous

    npm’s approach to semantic versioning: fork EventEmitter, bump the numeral, add onAny(), declare “we’re faster,” and by EventEmitter7 the only event anyone subscribes to is “security advisory.”

  7. Anonymous

    npm EventEmitters: because Node's stdlib emit() was too pure - needed 7 impure forks to handle real-world listener leaks

  8. @pyproman 4y

    Soon: EventEmitter42069

    1. @NiKryukov 4y

      It is nice, but EventEmitter69420 is even nicer

  9. @FLIPFL0P_T 4y

    Every new commit comes a new EventEmitter...

  10. @FLIPFL0P_T 4y

    What the hell will happen, if a bugged commit comes in?

  11. @FLIPFL0P_T 4y

    EventEmitter 2 -> EventEmitter1.9 Bugs in 2nd version detected, we had to downgrade our product But we will make it great again soon!

    1. @RiedleroD 4y

      branching: EventEmitter2.1 - fixed the bugs from 2.0 EventEmitter2.0a - added missing functionality from 2.0 without the bugs EventEmitter2.0b - merged just the bugs, not the features from 2.0

  12. @erizpl 4y

    https://xkcd.com/927/

  13. @igordata 4y

    EventEmitter 3.0. The only EventEmitter that emits not only the events, but the other EventEmitters!

  14. @AaronDewes 4y

    https://www.npmjs.com/package/eventemitterx https://www.npmjs.com/package/eventemitter8 https://www.npmjs.com/package/eventemitter9

  15. @AaronDewes 4y

    https://www.npmjs.com/package/eventemitter10

Use J and K for navigation