# Building blocks (/docs/composer/building-blocks)

> 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.

Compose the ready-made cron, storage, and streams Modules instead of building scheduled jobs, blob storage, or event streams yourself.

Location: Composer > Building blocks

Building blocks are Modules you compose instead of implementing a capability yourself. Each owns its internals and hands you a typed port, so adding one is a couple of lines. The first-party set ships inside `@prisma/composer-prisma-cloud`. It is small, and growing:

| Import                                                 | What you get                                                    | Exposes   |
| ------------------------------------------------------ | --------------------------------------------------------------- | --------- |
| `cron` from `@prisma/composer-prisma-cloud/cron`       | A scheduler that fires your jobs at your service on an interval | nothing   |
| `storage` from `@prisma/composer-prisma-cloud/storage` | An S3-backed blob store, credentials included                   | `store`   |
| `streams` from `@prisma/composer-prisma-cloud/streams` | Durable append-only event streams, backed by a `store`          | `streams` |

Before implementing a capability by hand, check whether a block already owns it. Wiring one in takes a few lines, while an integration you write yourself is code you maintain.

## Cron [#cron]

Cron is the block most apps want first. You supply two things, a schedule and a runner service that exposes the `trigger` contract, and the Module does the rest.

The schedule is the single source of truth for job ids and intervals:

```ts title="src/promotions/service.ts"
import { defineSchedule, triggerContract } from '@prisma/composer-prisma-cloud/cron';

export const schedule = defineSchedule({ rotateSpecial: '30s' });

export default compute({
  name: 'promotions',
  deps: { catalog: rpc(catalogContract) },
  build: node({ module: import.meta.url, entry: '../dist/server.mjs' }),
  expose: { trigger: triggerContract },
});
```

In the server, map each job id to work. `serveSchedule` checks the map against the schedule, so an unhandled job does not compile:

```ts title="src/promotions/server.ts"
import { serveSchedule } from '@prisma/composer-prisma-cloud/cron';

const handler = serveSchedule(service, schedule, {
  rotateSpecial: (deps) => deps.catalog.rotateSpecial({}),
});
```

In the module, the cron Module's boundary deps mirror the runner's own, so the root wires it like any other edge:

```ts title="module.ts"
provision(cron({ schedule, runner: promotionsService }), {
  deps: { catalog: catalog.rpc },
});
```

A runner that declares an `input` schema (see [Service input](https://www.prisma.io/docs/composer/service-input)) takes its binding on `cron()` itself, with `envSecret(...)` where the schema expects a secret. It is required exactly when the runner declares a schema, the same rule `provision()` applies:

```ts title="module.ts"
provision(
  cron({
    schedule,
    runner: ingestService,
    input: { token: envSecret('INGEST_TOKEN') },
  }),
  { deps: { catalog: catalog.rpc } },
);
```

The scheduler is the one service in your app that never sleeps. Compute scales an idle service to zero, and the scheduler receives no requests of its own, so it holds the platform's keep-awake guard for its whole lifetime. One warm instance per app is the cost of the clock; the runner sleeps like any other service and wakes when the scheduler calls it.

## Storage and streams [#storage-and-streams]

The `storage` Module provisions an S3-backed blob store, with its own Postgres and minted credentials, and exposes a `store` port. The `streams` Module builds durable append-only event streams on top of a `store`. For working versions, including the streams Module's secret binding, see [`examples/storage`](https://github.com/prisma/composer/tree/main/examples/storage) and [`examples/streams`](https://github.com/prisma/composer/tree/main/examples/streams) in the Composer repository.

If you want the raw S3 surface without the Module, provision a [`bucket` resource](https://www.prisma.io/docs/composer/object-storage) instead; the two share a contract kind, so a service wired to `s3()` can be rewired to a `bucket` without changing its declaration.

## Where new blocks come from [#where-new-blocks-come-from]

An **extension** is a package that brings its own Modules, resources, or deploy target, using the same mechanism `@prisma/composer-prisma-cloud` itself uses. The convention is an npm package named `prisma-composer-*`, which is how you and your agent find one. An extension is installed like any dependency and enters the deploy through the `extensions` array in `prisma-composer.config.ts`.

The ecosystem is new: today the three Modules above plus the ones you write are the whole set. Treat `prisma-composer-*` as the place to look, and check that a package actually exists on npm before depending on it.

## Next steps [#next-steps]

* [Apps and Modules](https://www.prisma.io/docs/composer/apps-and-modules): write a reusable Module of your own.
* [Object storage](https://www.prisma.io/docs/composer/object-storage): the raw bucket resource.

## Related pages

- [`Apps and Modules`](https://www.prisma.io/docs/composer/apps-and-modules): How services, resources, and Modules compose into a Prisma App, and how provision() wires them together.
- [`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 ORM 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.