Cartridges

A cartridge is a package that owns one job and the resources it needs. A service is the named interface callers use for that job. Its service tag identifies the service. A Layer describes how to build services and supply their dependencies.

An Alchemy Layer can also declare the cloud resources behind a service. Layer.provide supplies the chosen implementation to the application. Replacing that Layer changes the implementation and its dependencies without changing callers.

The database cartridge makes this concrete. DatabaseVendor represents either D1 or Hyperdrive Postgres. packages/database/src/d1.ts declares the D1 schema and database.

packages/database/src/hyperdrive-postgres.ts declares the Postgres schema, Hyperdrive connection, and migration registration. Both provide the same RunLog service. The auth cartridge consumes DatabaseVendor.

packages/auth/src/auth.ts picks Better Auth16’s D1 or Hyperdrive adapter.

A cartridge must:

Removal must leave no loose resources or broken imports. Delete the package and its provision line, then run pnpm turbo run check test build.

A rectangular grey Super NES cartridge above a rounded Super Famicom cartridge, with their moulded shells and connector openings visible.
A Super NES cartridge above a Super Famicom cartridge. Photo by Evan-Amos, 2011; public domain (PD-self). Source: Wikimedia Commons.

Analytics18 is a second running example: packages/events owns capture and its Basin resources. README lists the steps needed to remove it. packages/subscriber-delivery is a provider adapter behind core’s ports. One-line infrastructure removal remains unproven for that package.

Where the pattern comes from

This project calls the pattern a “cartridge”. Sam describes Layers as a way to carry infrastructure and permissions with a service, and calls the idea “SaaS as NPM.” devtools.fm, 21:15. He also describes swapping implementations by providing different Layers. Effect Office Hours 27, 34:35.

Interchangeability between provider implementations remains unproven. Sam describes test or development Layers for infrastructure and a type error when code still requires a removed binding. Happy Path 116, 15:25 Effect Office Hours 27, 07:05.

See one capability, every surface18 for the shared contract and a clean playground9 for the house rule9 behind these boundaries.

Sources

  1. rat-stack/VISION.md at main · joelhooks/rat-stack · GitHub. GitHub joelhooks/rat-stack. Cartridge criteria; used for labeling, composition, removal, and self-containment. Accessed 2026-10-01.
  2. rat-stack/packages/database/src/vendor.ts at main · joelhooks/rat-stack · GitHub. GitHub joelhooks/rat-stack. Database vendor boundary; used for the D1 and Hyperdrive example. Accessed 2026-10-01.
  3. rat-stack/packages/auth/src/auth.ts at main · joelhooks/rat-stack · GitHub. GitHub joelhooks/rat-stack. Auth composition; used for the cartridge that consumes the database vendor. Accessed 2026-10-01.

Last changed 2026-10-07 in e73c9d9. Source on GitHub. Change log.

Linked from

  1. A clean playground. rat-stack does real work with packages that stay easy to add and remove.

    A cartridge is a package for one job, with the resources that job needs.

  2. A Layer as constructor. Sam Goodwin compares an Effect Layer that builds a service to a constructor.

    See Sam Goodwin on Alchemy and cartridges.¶

  3. A service captures its construction dependencies. Build a service with its dependencies, then expose methods that callers can use without rebuilding the graph.

    rat-stack also uses capability projections, cartridge packages, and a no-comments rule.¶

  4. add-a-store. Add persistence through a service named for an application job, with validation, vendor Layers, migrations, bounded reads, and shared backend tests.

    Keep each vendor’s Drizzle operations in the cartridge, a package for one job with its implementation and required infrastructure.

  5. Agent guide. An Effect stack so pure (aspirational) Kit Langton will blush.

    Cartridges — A cartridge owns one job and brings the infrastructure its service needs.

  6. Agent rules for rat-stack (AGENTS.md). What you may change, which commands to run, and which changes need approval.
  7. An MCP your users want. Rhys Sullivan's practical guide gives rat-stack a checklist for useful MCP tools.

    See one capability, every surface and the cartridges page for the contracts and auth boundary.¶

  8. Analytics. One event per HTTP request, stored unchanged for queries to select and interpret later.

    The packages/events cartridge is a package for one job, with its implementation and required infrastructure.

  9. Auth. Email and password sign-in through Better Auth, with the signed-in person provided to each RPC call.

    The auth cartridge, packages/auth, is a package for one job with its implementation and required infrastructure.

  10. Capture first, shape later. Store events without rejecting them for an evolving event shape, then decide their shape when you query.

    In rat-stack, the packages/events cartridge owns event recording and its resources.

  11. Change log. What changed in the files served here, newest first.

    Cartridges — edited: feat(learn): teach the next twenty cards with plain lines, diagrams and snippets

  12. Database. One interface records action runs and their outcomes in either Cloudflare D1 or Postgres through Hyperdrive.

    The database cartridge, packages/database, is a package for one job, with its implementation and required infrastructure.

  13. Effect + Alchemy peer patterns. Source-grounded patterns from repos on nearby Effect and Alchemy pins.

    Adapt this for the database cartridge.

  14. Effect + Alchemy peers. Public repositories that share rat-stack's prerelease lines.
  15. Feature flags. Typed feature flags with owners, removal dates, and stable subject rollouts.

    The packages/flags cartridge evaluates typed flags.

  16. Full agent guide. An Effect stack so pure (aspirational) Kit Langton will blush.
  17. Hexagonal architecture. Ports name the application's jobs; adapters connect them to the outside world.

    Cartridges adds rat-stack’s own packaging and removal test, including infrastructure supplied through Layer.provide.

  18. Hosted agent interfaces. Discovery documents, HTTP, MCP, A2A, and bounded code mode expose the public reference to agents.

    A reusable cartridge for agent interfaces remains planned.

  19. Infrastructure as effects. Sam Goodwin relates application operations to infrastructure requirements in one typed program.

    A cartridge is a package that owns one job and the resources it needs.

  20. Layer composition makes dependencies explicit. Supply a service's dependencies, choose which services remain visible, and reuse Layer identity within a build.

    A cartridge packages one job and its infrastructure.

  21. Learn mode presents concepts at useful depths. An agent presents source-derived concepts during real work and keeps learning events in a private local log.

    The learning cartridge provides the adapter through @rat-stack/learn/local.

  22. Learn the stack | rat-stack. Hands-on guides to Effect actions, XState lifecycles, and the seams between stack pieces.
    Link context

    uncomplect — Find responsibilities that a rat-stack design combines, separate them into capabilities, cartridges, machines, features, and clients, and enforce that separation through types and checks.

  23. One capability, every surface. A schema-typed contract and one handler feed every interface rat-stack keeps.

    Analytics shows a separate infrastructure cartridge; interest signup shows core ports with a delivery adapter outside core.

  24. Property-based testing. State a rule that must hold for every input, then let a generator hunt for the smallest input that breaks it.

    The capture-first events cartridge is tested this way.

  25. Purpose and boundaries of rat-stack (VISION.md). What this starter is for and what a useful copy should keep.

    Types, the fence, and cartridges that pull out cleanly raise the floor for every agent working here.

  26. Rat King binds agents into one encrypted network. Rat King plans an encrypted AT Protocol agent network built on rat-stack.

    Cartridges explain the service and infrastructure pattern.

  27. Rat Stack lore | rat-stack. Short, source-grounded notes on the ideas and decisions behind rat-stack.

    Cartridges — A cartridge owns one job and brings the infrastructure its service needs.

  28. Rat Stack systems | rat-stack. The systems rat-stack ships, the standard each keeps, and how to check it.

    The hosted agent front door records discovery, MCP versions, API, A2A, and sandbox limits; extracting it into a generic cartridge remains future work.

  29. rat-stack. An Effect stack so pure (aspirational) Kit Langton will blush.

    The hosted agent interfaces run in Mischief; extracting them into a separate cartridge is still work to do.

  30. rat-stack-mode. Route non-trivial rat-stack code, data, design, investigation, and documentation tasks to every matching playbook and principle.

    A cartridge is a package for one job with its implementation and required infrastructure.¶

  31. Rat's Nest keeps the code public and the inventory private. Joel's purpose-built on-prem cloud uses rat-stack and Alchemy, with private inventory outside the public repo.

    Cartridges explain rat-stack’s service and infrastructure pattern.¶

  32. Source change history (log.md). The generated change log as Markdown.

    Cartridges — edited: feat(learn): teach the next twenty cards with plain lines, diagrams and snippets

  33. Structure an Effect codebase by domain. Start with folders for application work, services and Layers in the same file, and startup code that supplies implementations.
  34. Tests prove behavior through supplied services. Supply services through Layers, choose properties or models for domain rules, and reject tests that cannot detect broken behavior.

    Live-provider behavior needs separate proof for each cartridge.¶

  35. uncomplect. Find responsibilities that a rat-stack design combines, separate them into capabilities, cartridges, machines, features, and clients, and enforce that separation through types and checks. Use when asked to simplify, review, or replace a design, "what would Rich Hickey do", "optimize for deletion", or "define this error out of existence".
  36. Worker init runs twice. Alchemy Worker initialization runs in deploy and runtime contexts, so resource declarations need a boundary.

    See cartridges for the rule that each resource belongs to its Layer and the fence for the required tests that check this separation.¶

Unlinked mentions (9)