# Apps and Modules (/docs/composer/apps-and-modules)

> For the complete Prisma documentation index, see [llms.txt](https://www.prisma.io/docs/llms.txt). A markdown version of any docs page is available by appending `.md` to its URL.

How services, resources, and Modules compose into a Prisma App, and how provision() wires them together.

Location: Composer > Apps and Modules

A **Prisma App** is a tree of Modules composed in TypeScript. At the leaves are **services**, the units that run your code, and **resources**, stateful things like a Postgres database. A parent Module wires them together; your code never participates in the wiring, it only receives the results.

For example, a store app might be one root module containing a `catalog` Module (an API service plus its own database), an `orders` Module, and a `storefront` Next.js service that calls both. Each piece declares what it needs, and the root wires the pieces together.

This matters because the wiring is data the compiler can check. A dependency wired to the wrong producer, or a missing one, fails `tsc` and fails the deploy, instead of failing at runtime in production.

## The service declaration [#the-service-declaration]

A service declares everything about itself in one `compute()` call. It is pure data, with no behavior:

```ts
compute({
  name: 'auth',                  // the service's name in the app graph
  deps: { db: postgres() },      // what it needs         -> read via service.load()
  input: authInput,              // its incoming config   -> read via service.input()
  build: node({ module: import.meta.url, entry: '../dist/server.mjs' }),
  expose: { rpc: authContract }, // what it offers to other services
});
```

Dependencies and input are two deliberately separate channels with two separate accessors. A dependency is a live connection to another node; input is data, plain values and credentials together, declared as one schema (see [Service input](https://www.prisma.io/docs/composer/service-input)). Your code contains no configuration reads and no URLs, which is what makes every environment (production, a stage, a test) a different set of injected values and nothing more.

## The root module [#the-root-module]

The root module is the app. The Composer CLI loads its default export:

```ts title="module.ts"
import { module } from '@prisma/composer';
import authModule from './src/auth/module.ts';
import storefrontService from './src/storefront/service.ts';

export default module('my-app', ({ provision }) => {
  const auth = provision(authModule);
  provision(storefrontService, { deps: { auth: auth.rpc } });
});
```

`provision(node, opts?)` places a node in the graph and returns a ref carrying one port per exposed contract. Its options:

* `id`: the node's name in the graph, defaulting to its own `name`. Set it explicitly when the default stutters; a service named `auth` inside a module named `auth` would read as `auth.auth`.
* `deps`: a value for each declared dependency slot, either another provisioned ref or an exposed port.
* `input`: the service's input binding, required exactly when the service declares an input schema. See [Service input](https://www.prisma.io/docs/composer/service-input).
* `secrets`: for a Module boundary, a binding for each forwarded secret need.

Two naming rules the platform enforces: provision names must be at least three characters (call a database `'database'`, not `'db'`; the wiring key on the service side can still be `db`), and ids must be unique within their module.

## Reusable Modules [#reusable-modules]

When a service and its database belong together, package them as a **Module**: a unit that owns its internals and offers only typed ports. A consumer provisions the Module and wires its exposed contract; it never sees, and can never reach, the database inside.

A Module declares its boundary (what it needs, what it offers) in the second argument, wires its internals in the builder function, and returns the ports it promised:

```ts title="src/auth/module.ts"
import { module, secret } from '@prisma/composer';
import { postgres } from '@prisma/composer-prisma-cloud';
import { authContract } from './contract.ts';
import authService from './service.ts';

export default module(
  'auth',
  { secrets: { signingKey: secret() }, expose: { rpc: authContract } },
  ({ secrets, provision }) => {
    const db = provision(postgres({ name: 'database' }));
    const service = provision(authService, {
      id: 'service',
      deps: { db },
      input: { signingKey: secrets.signingKey },
    });
    return { rpc: service.rpc };
  },
);
```

The boundary declares `secrets: { signingKey: secret() }`: a nameless need the Module forwards without ever learning the platform variable's name. The root binds it:

```ts title="module.ts"
const auth = provision(authModule, {
  secrets: { signingKey: envSecret('AUTH_SIGNING_SECRET') },
});
provision(storefrontService, { deps: { auth: auth.rpc } });
```

A Module can also declare boundary `deps`: inputs its parent must supply, wired exactly like a service's. The root module you already have is the outermost Module, with no boundary at all.

## When to reach for a Module [#when-to-reach-for-a-module]

* **Compose before you write.** Ready-made Modules for scheduled jobs, blob storage, and event streams ship with the framework; wiring one in is a couple of lines. See [Building blocks](https://www.prisma.io/docs/composer/building-blocks).
* **Package what belongs together.** A service that owns a database, or a pair of services that only make sense as a unit, is a Module.
* **Keep the app graph readable.** The deploy prints the module tree with dotted addresses (`auth.service`), so the structure you author is the structure you operate.

## Next steps [#next-steps]

* [Services and contracts](https://www.prisma.io/docs/composer/services-and-contracts): what happens on the wire between services.
* [Service input](https://www.prisma.io/docs/composer/service-input): configuration and secrets as one schema.
* [Building blocks](https://www.prisma.io/docs/composer/building-blocks): the Modules that ship with the framework.

## Related pages

- [`Building blocks`](https://www.prisma.io/docs/composer/building-blocks): Compose the ready-made cron, storage, and streams Modules instead of building scheduled jobs, blob storage, or event streams yourself.
- [`Core concepts`](https://www.prisma.io/docs/composer/core-concepts): The ideas every Composer declaration and command builds on: services, resources, Modules, ports, contracts, stages, and the deploy model.
- [`Databases`](https://www.prisma.io/docs/composer/databases): Give a service a Postgres database, either as a plain connection or typed by a Prisma 8 contract with managed migrations.
- [`Deploying`](https://www.prisma.io/docs/composer/deploying): Deploy a Prisma App to production or an isolated stage, run it in CI, and tear environments down safely.
- [`Getting started`](https://www.prisma.io/docs/composer/getting-started): Build a two-service Prisma App from an empty directory and run it on your machine with one command.