Guides

Many Products, One Federation

How one Federation can serve multiple products without mixing product differences with shared infrastructure.

When many products share one runtime, the goal is not “save one server.” The goal is to separate shared infrastructure from product-specific differences.

What should be shared:

  • provider env
  • model directory
  • service routing
  • hooks, usage, and logs
  • user_token verification

What should stay in each product:

  • pages and interaction
  • the user system
  • plan, order, and balance rules
  • product-specific brand, positioning, and pricing

One diagram for the reuse boundary

Product AFor example, a web tool.bureau_id = web
Product BFor example, a Chrome extension.bureau_id = extension
Product CFor example, a client demo or internal tool.bureau_id = demo
FederationReuses the model directory, provider env, service logic, usage records, and hooks.

How to think about bureau_id

bureau_id is a product boundary, not a model boundary.

It is useful for:

  • identifying which product sent the call
  • deciding whether a product is still active
  • telling hooks where usage should be recorded
  • separating one user’s activity across different products

A common pattern is one stable bureau_id per product:

const issued = await admin.service("accounts").action("tokens/issue").invoke({
  bureau_id: "demo",
  user_id: "user_123",
  metadata: {
    plan: "starter",
    channel: "extension",
  },
});

What belongs in token metadata

bureau_id says which product this is. Token metadata is better for the user’s business state inside that product.

Common fields:

  • plan
  • organization_id
  • channel
  • feature_flag
  • team_id

That lets hooks differentiate behavior with ctx.bureau and ctx.user.metadata instead of cloning City for each city.

City side

  • keeps routes, UI, and business experience
  • uses User City
  • only holds user_token (which contains bureau_id)

Business backend

  • owns login, orders, balance, subscriptions, and business data
  • uses FederationAdmin in a trusted environment
  • issues user_token after a successful login

City

  • owns the model directory
  • owns provider calls
  • owns usage and hooks
  • owns the reusable AI service layer

When to create a new city

Usually worth creating a new city when:

  • it is a separate city or market
  • it needs to be paused or activated independently
  • it needs independent usage reporting or business strategy
  • you need to separate web app, extension, client demo, and other city surfaces

Usually not worth creating a new city when:

  • it is only another page in the same city
  • it is only a feature flag inside the same city
  • it is just another conversation/session for one user

Those are better kept inside your own business system or token metadata.