Proposal: separate paywall / middleware from the base x402 typescript package
Summary
Refactor paywall-related code out of the x402 TypeScript package and move it into one or more separate packages (e.g., x402-paywall or x402-middleware). The core x402 package should remain a small, vendor-agnostic protocol library containing only abstractions and basic functionality.
Rationale
- Separation of concerns
- The x402 package is a protocol base package and should only contain protocol abstractions and minimal utilities. Paywall is a higher-level feature used by middleware and applications, not part of the protocol itself.
- Bundle size and integration limits
- The current paywall implementation pulls heavy frontend and vendor dependencies (React, wagmi, @coinbase/onchainkit, etc.), which dramatically increases package size.
- This causes integration problems in size-constrained environments. Example: a basic edge function implementation depending on
x402and@coinbase/x402produced a bundle of 35.32 MB — exceeding Supabase Edge Function limits (20 MB).
- Vendor-agnostic core
- The base package should be vendor-agnostic. The current PaywallConfig and default paywall depend on vendor-specific concepts (e.g., cdpClientKey and cdp/onchainkit), coupling core protocol code to specific middleware providers.
Proposal
- Extract paywall/middleware code into a separate package (or packages), for example:
x402-paywall- or
x402-middleware
- Keep
x402as a lightweight, vendor-agnostic protocol package that provides only core abstractions and utilities. - Provide the paywall implementation(s) from a vender specific package like
@coinbase/x402-paywall; downstream projects can opt-in by adding the paywall package as a dependency (similar to how facilitator code is provided today).
Benefits
- Smaller, cleaner core package: easier to audit, maintain, and reason about the protocol.
- Reduced bundle sizes for consumers who only need protocol functionality.
- Better compatibility with size-limited runtimes (edge functions, serverless).
- Clear vendor separation: paywall implementations can be vendor-specific without polluting the protocol package.
- Easier to extend: multiple paywall implementations (vendor-specific or generic) can be published independently.
This is a solid way to go.
We did this with our x402 implementation inside of Faremeter, and it worked well. For something like running the middleware, the dependencies end up looking like:
@logtape/logtape- 636k - We use this on Faremeter for all of our logging, but this will soon become optionalarktype- 332k - ArkType handles all of our type creation and runtime validation.@faremeter/types- 116k - All of your base x402 type definitions (and some helpers for different chains).@faremeter/middleware- 200k - Compatible middleware for a bunch of systems (e.g. express, Hono).@faremeter/info- 118k - Helpers for looking up network names and asset addresses.
... and of course you can bundle/tree shake that, and it'll get down to a much smaller size. It lets you compose things much more easily than just having a huge monolith.
We've spoken with @CarsonRoscoe about this approach, and he's definitely aware of the benefits as things move forward into coinbase/x402 v2.