# How Sandloom works

Your product is a set of isolated modules. They reach the framework through one public SDK, and drivers connect the framework to your backends.

[Business modules](<https://sandloom.dev/docs/modules/index.md>)Your application code

**Orders**Order logic &amp; data

[**Contracts**Typed calls &amp; replies↔](<https://sandloom.dev/docs/modules/between/contracts/index.md>) [**Events**Asynchronous reactions→](<https://sandloom.dev/docs/modules/between/events/index.md>)

**Catalog**Product logic &amp; data

Standard modules, same boundariesIdentity · Tenancy · Billing

use the public SDK

[Public SDK`sandloom.sdk`](<https://sandloom.dev/docs/reference/sdk/index.md>)

**Kernel**Provided by Sandloom

TransactionsAccess checksOutbox &amp; inboxLocal / RPC routing

Each application or service runs its own kernel.

resolve infrastructure capabilities

[Drivers](<https://sandloom.dev/docs/infrastructure/index.md>)Selected by configuration

Each driver connects the runtime to a concrete backend.

Database · sqlalchemy**PostgreSQL**

Cache**Redis**

Events · streams**Redis Streams**

Files · local**Disk / volume**

Tasks · celery**Celery**

Email**SMTP**

One modular application. The same module code in a monolith or separate services.

## Design principles

- **A module stands alone.** It imports only the public SDK and generated contracts, never another module. You or a coding agent can change one by reading it and the contracts it calls.
- **The framework owns what is easy to get wrong.** It commits the transaction, authenticates each route unless the route declares `public(reason=...)`, and delivers events through an outbox. Weakening a default takes a visible line of code. Which resources a user may touch is yours to declare with [`require`](<https://sandloom.dev/docs/modules/http/authorization/index.md>).
- **Configuration decides where things run.** It selects which process loads which module and which backend each capability uses. Moving a running module's existing data to its own database is a separate, [explicit step](<https://sandloom.dev/docs/operate/split-into-services/#existing-data>).
- **A machine checks the rules.** `sandloom check` and the startup checks enforce the boundaries and name the fix: `sandloom explain <code>`.

## Modules and drivers

A module is what your product does. A driver is what it runs on.

|  | Module | Driver |
| --- | --- | --- |
| **What it is** | one slice of the business, such as orders or billing | a connection to a backend, such as Redis or SMTP |
| **Who uses it** | your product's users, through routes | modules, through the SDK; they never name the driver |
| **Imports** | `sandloom.sdk` | `sandloom.driverkit` |
| **Found through** | your `modules` package or the `sandloom.modules` entry point | the `sandloom.drivers` entry point |
| **Selected by** | `SANDLOOM_MODULES` | `INFRA` |
| **Created with** | `sandloom add module <name>` | [your own package](<https://sandloom.dev/docs/infrastructure/write-a-driver/index.md>) |

Modules talk to each other in two ways: [events](<https://sandloom.dev/docs/modules/between/events/index.md>) when something has happened, and typed [contracts](<https://sandloom.dev/docs/modules/between/contracts/index.md>) when one needs an answer now.

## What do I write?

| I want to | I write |
| --- | --- |
| add a product feature | a [module](<https://sandloom.dev/docs/modules/create/index.md>) |
| react to something another module did | an [event consumer](<https://sandloom.dev/docs/modules/between/add-consumer/index.md>) |
| ask another module for data now | a call to its [contract](<https://sandloom.dev/docs/modules/between/add-contract/index.md>) |
| run a process across modules, with undo | a [saga](<https://sandloom.dev/docs/modules/between/add-saga/index.md>) |
| show a list that spans modules | a [projection](<https://sandloom.dev/docs/modules/between/add-projection/index.md>) |
| change how identity, tenancy or billing behave | a [customization](<https://sandloom.dev/docs/modules/standard/customize/index.md>) |
| send notifications through a new service | a [driver](<https://sandloom.dev/docs/infrastructure/write-a-driver/index.md>) |
| run a module as its own service | [configuration](<https://sandloom.dev/docs/operate/split-into-services/index.md>), no module code |
