Skip to main content

Building SDK Kit: Patterns From Production Systems

·9 min read·
Khmer decorative icon

Short answer

The useful part of JSTag was not the product shape. It was the infrastructure underneath it: minimal core, functional plugins, capability injection, and event-driven coordination.
I kept seeing the same architectural patterns emerge across different projects, so I went back to the production source I trusted most and studied why those patterns had survived. SDK Kit became the extraction: keep the battle-tested composition layer, strip away the product opinions, and validate it by building on top of it.
What held
A minimal microkernel plus functional plugins gave the system the right balance of stability and extension. Capability injection kept dependencies explicit. Events kept coordination loose.
The distinction
JSTag as a product is opinionated and batteries-included. The infrastructure under it is generic. SDK Kit keeps the infrastructure and makes composition explicit instead of automatic.
Why it matters
Production systems teach pattern extraction better than textbooks because every design choice has already been pressed by scale, integration pressure, and time.

Over winter break, I kept noticing the same shape show up in my side projects.

I had built dev-agent during our November vibeathon. Then I started sketching Auth HI!, a Chrome extension for injecting auth headers. Then I started thinking about Experience SDK, a personalization runtime. Different products, different surfaces, same architecture trying to happen underneath: plugins, events, configuration, clear boundaries, optional capabilities.

If I keep rebuilding the same thing three times, I either understand the pattern well enough to name it, or I don't understand it at all and I'm just getting lucky.

So I went back to the source I trusted most: JSTag.

why JSTag was worth studying

JSTag is Lytics' web SDK. It has been in production long enough to earn its confidence. It has lived through scale, third-party integrations, consent constraints, transport decisions, years of product pressure, and all the boring things that quietly destroy elegant architecture if the architecture isn't actually good.

That was what interested me.

I wasn't trying to copy the product. I was trying to understand which parts of its shape were there because Lytics is Lytics, and which parts were there because SDKs under real pressure keep needing the same infrastructure.

the repeat-pattern moment

I wasn't studying JSTag to learn "how to build a CDP SDK." I was studying it because I kept seeing the same coordination problems show up in completely different projects.

Auth HI! needed to coordinate storage, pattern matching, and request interception inside the weird constraints of a Chrome extension.

Experience SDK needed optional feature surfaces, explainable decisions, and the ability to load only what a marketer actually uses.

Neither of those products is JSTag. But the underlying problems rhyme.

What in JSTag is product opinion, and what in JSTag is reusable infrastructure?

Once I started looking through that lens, the architecture opened up.

what JSTag was actually teaching

What JSTag gave me was a way of composing behavior.

At the center is a small core. Plugins register themselves through use(). Each plugin is a function. No class hierarchy. And that function receives what it needs explicitly: capabilities, instance access, configuration.

function use(closure: PluginClosure): SDK {
  const plugin = { ns, defaults, expose, emit, on };
  closure(plugin, this, this.config);
  return this;
}

What I liked in it was what it refused to do.

It refuses hidden dependencies. It refuses ambient global state. It refuses tight coupling as the default coordination model.

Three patterns inside JSTag turned out to be the ones worth keeping.

minimal core

The core is small: plugin registration and a few utilities. Everything else comes from plugins.

That buys you a kind of stability that is easy to underestimate. The core does not need to know about analytics, storage, consent, transport, or whatever the next product decision turns out to be. It just needs to provide a dependable place where those things can attach.

For SDKs, that matters a lot. Product needs change. Integrations multiply. The thing you want least is a center that has to be rewritten every time the edge gets more complicated.

capability injection

Plugins get the capabilities they need as arguments. That sounds like a dry design point until you work on systems where the opposite is true.

When dependencies are explicit:

  • testing gets easier
  • environment changes hurt less
  • plugins stay portable
  • the architecture is readable from the function signature instead of from tribal knowledge

You can see the difference immediately between a plugin that receives emit, on, and config directly, and a plugin that reaches into window, touches internal state, or assumes a runtime it was never promised.

The first one is infrastructure. The second one is a future debugging session.

event-driven coordination

Plugins coordinating through events stay loose. A storage plugin can emit that something changed. Another plugin can react without either one knowing much about the other. That makes the system easier to extend, easier to replace in parts, and much easier to debug because behavior surfaces as signals instead of hiding inside call chains.

I felt that immediately in SDK Kit too. When behavior moved through events, debugging stayed local. I wasn't spelunking through tangled plugin-to-plugin method calls trying to find who secretly owned what.

what I did not want to copy

JSTag as a product is opinionated and batteries-included. It should be. Its job is to collect data for a specific platform with specific needs. Auto-loading essential plugins makes sense in that world. Strong product defaults make sense in that world.

But if I had copied that shape wholesale into SDK Kit, I would have copied the wrong thing.

I wasn't trying to make "JSTag, but generic." I wanted the infrastructure without the product assumptions.

The distinction I ended up with was simple:

  • JSTag demonstrates the patterns at scale
  • SDK Kit turns those patterns into a reusable composition layer

So SDK Kit keeps the minimal core, the functional plugin signature, the capability injection, and the event-driven coordination. It doesn't auto-load a worldview.

Users compose only what they need.

That was the part worth carrying forward.

building is what made the extraction honest

Production systems can make every design decision look inevitable once they have survived long enough. The only way I know to test whether I actually understand a pattern is to build with it.

SDK Kit was that test.

Auth HI! was the harsher test.

Chrome extensions are good at exposing architectural weakness. Service worker constraints, request interception, message-passing between UI and background logic, storage quirks, rule limits. The surface looks small until you build on it and realize the coordination problem is the product.

That was useful because the architecture had to hold or fall apart quickly.

What held up:

  • plugins stayed isolated enough to test without drama
  • events made behavior visible
  • low coupling kept changes local
  • the core stayed boring, which is exactly what you want from the core

Then the same infrastructure made sense again for Experience SDK, which is a completely different product shape. That was enough evidence for me. If the same composition layer works for a Chrome extension and a personalization runtime, you are probably looking at infrastructure.

what I actually learned

Production systems teach composition better than textbooks do.

Production code has already been pushed by real constraints. Scale, integrations, time, migration pressure, all the unglamorous things that reveal whether a pattern is structural or just clever.

Reading JSTag closely helped me separate two categories of thought that had been blurred together in my head:

  • how a product chooses to use an architecture
  • what the architecture itself is good at

I think it is one of the reasons building from production references can accelerate learning so much. You are not starting from greenfield purity. You are starting from something that has already survived.

what survived because it had to?

the edges I still see

The extraction is not finished. Building SDK Kit surfaced a few open edges clearly enough that I would not pretend otherwise.

Plugin dependencies are still implicit. Order matters in some cases, and while documentation can carry that for a while, I don't think documentation is the final answer.

Plugin-to-plugin extension is still unresolved. JSTag's hold() model is powerful, but it also introduces more coupling. I have not fully decided where I want that tradeoff to land in SDK Kit.

And lifecycle integration testing still has room to grow. Isolated plugin tests are not the same thing as proving that a whole coordination chain behaves in the right order when the system is actually live.

Those are real edges. I would rather see them clearly than write past them.

what I'm keeping

What I'm keeping is the method:

  • notice the pattern that keeps repeating
  • go to the production source that has already survived
  • separate the infrastructure from the product opinion
  • validate the extraction by building

That loop gave me SDK Kit. It also gave me a cleaner way to study systems I want to learn from without copying the wrong layer of the thing.

FAQ

What is plugin-based SDK architecture?

It is an SDK design where a minimal core provides registration and basic coordination, while features arrive through plugins rather than a large inheritance tree or a fixed monolith.

What is capability injection in SDK design?

Capability injection means plugins receive what they need explicitly as parameters: things like namespace registration, configuration access, event emission, and event subscription. That keeps dependencies visible and makes testing and portability much easier.

Why does event-driven coordination work well in SDKs?

Because it keeps plugins loosely coupled. One part of the system can emit behavior-relevant signals without hard-coding knowledge of every other part that might react to them.

What is the difference between JSTag and SDK Kit?

JSTag is a production product with strong opinions and auto-loaded behavior because it serves a specific data collection job. SDK Kit keeps the reusable infrastructure underneath that shape and makes composition explicit instead of automatic.

How do you extract reusable patterns from a production system?

Study the code closely enough to tell which parts exist because the product needs them and which parts exist because the architecture keeps surviving pressure. Then build something new with only the structural layer and see what still holds.

Khmer decorative icon
Related Project

SDK Kit

Plugin-based SDK framework extracted from production patterns. Minimal core with capability injection, event-driven coordination, and functional plugins.

Related

Khmer decorative icon