You're given a very basic set of primitive nodes, from which you can construct pretty much anything else. But those things you construct will never be "nodes" themselves. You can't create synthetic nodes or subclass node types. But then many of the basic nodes are useful on their own. So you end up in a bind of having two different provenance branches of audio "node-like" things and need to know which is which before you can connect any one of Column A to any other of Column B, or vice versa.
You're also on your own in terms of keeping track of those connections. Once a node is connected to another node, there is no in-API way of telling what nodes a node is connected to, or what nodes connect to a given node. There's a whole, huge, potentially cyclical graph structure sitting around in memory that you can manipulate but never inspect.
With how hard everything is to keep track of what is where, you can easily end up in a situation where old, now-disconnected or unused nodes stay resident in memory and never get garbage collected. Some developers then punt on tracking connections at all and expect the user to reload the page if there is a major change in audio setup (coughcoughGoogleOmnitonecoughcough).
So when people talk about how Web-based gaming really hasn't taken off or replaced the haunting specter of Adobe Flash, and then point at WebGL as the problemm, I kind of laugh. WebGL is the least of your worries.
Anyway.
Elementary Audio seems to end-run around all that by A) only letting you declaritively define your audio setup, and B) running everything in a single Audio Worklet, thereby bypassing the majority of the Web Audio API.