Schemas define the boundary
Schema defines accepted values, runtime checks, and associated TypeScript types. Decoding checks external input and produces an application value. Encoding produces its external representation. A codec connects these two representations.¶
Define the values the application accepts before writing the handler. Decode unknown input at the boundary. Encode results through the declared output schema.¶
Use one model for types and runtime checks
Schema.Struct describes a record. Schema.Literals describes a fixed set of alternatives.
A schema’s Type describes its decoded value; Encoded describes its external representation.
Those representations can differ when a codec transforms values.¶
const ContentKind = Schema.Literals(["law", "skill", "lore", "prompt"]);
export const SearchMatch = Schema.Struct({
description: Schema.String,
digest: Schema.String,
excerpt: Schema.String,
id: Schema.String,
kind: ContentKind,
routePath: Schema.String,
score: Schema.Finite,
title: Schema.String,
});Content kinds have four accepted values. A match must carry the declared fields and a finite score.¶
Derive the TypeScript type from the schema rather than maintaining a second interface.
Use Schema.Union when accepted alternatives have different shapes, including tagged failures.¶
Put the schemas in the contract
A contract declares an action’s input, output, and failures. The file-inspection contract names its input, result, and failure.¶
export const inspectFileContract = defineContract("inspectFile", {
annotations: { idempotent: true, readOnly: true },
description: "Count bytes, characters, words, and lines in a file",
failure: FileStatsError,
input: Schema.Struct({
path: Schema.String.annotate({ description: "File to inspect" }),
}),
output: FileStatsSchema,
});The schemas check values at runtime.¶
Decode before dispatch
Schema.decodeUnknownEffect accepts unknown input and keeps decoding failures in the Effect error channel.
Our code-mode invoker calls the handler only after decoding succeeds.¶
return Schema.decodeUnknownEffect(item.contract.input)(input).pipe(
Effect.matchEffect({
onFailure: () =>
Effect.succeed(
invokeFailure(
"InvalidInput",
"Capability input does not match its schema"
)
),
onSuccess: (decoded) =>
run(decoded).pipe(
Effect.provideContext(context),
Effect.matchEffect({
onFailure: (error) =>Rejected input becomes InvalidInput. The domain handler receives the decoded value after validation.¶
The same invoker uses Schema.encodeUnknownEffect for declared outputs and failures.
For an already-typed value, Schema.encodeEffect supplies the typed encoding API.
JSON serialization alone does not check whether a result satisfies its contract.¶
A schema states what a value means
The interest contract separates contact consent from sharing consent. Accepting contact does not authorize sharing. Its answer fields are bounded strings.¶
AbuseVerdictSchema describes a hold flag, a finite score between zero and one, and signal names.
The AbuseVerdict type derives from that schema.
These are domain decisions; Schema does not choose them for us.¶
A generated input also does not supply a behavior assertion. Property tests23 still need an independent rule that those values must satisfy.¶
Common wrong approach
A type assertion changes what TypeScript believes. It does not reject a malformed external value. Decode at the boundary instead of casting it into a domain type.¶
Hand-written JSON parsing followed by a copied interface creates two models that can drift. Use the schema’s decoding and encoding APIs. Report malformed input separately from an expected domain refusal39.¶
Effect idiom and house rule
- Schema defines runtime decoding, encoding, and the associated TypeScript types.¶
- In rat-stack, one capability contract27 supplies schemas to every interface projection.¶
- rat-stack also uses capabilities and a bodyless HTTP 400 response for malformed input.¶
See also: one schema, three surfaces25, OpenAPI refusals14, services26, and testing22.¶
Sources
- Effect contributors. 2026. Schema. Effect 4.0.0.. Effect-TS. Struct, Literals, Union, schema-derived types, and effectful decoding and encoding. Accessed 2026-10-06.
- Effect contributors. 2026. Schema basics.. Effect-TS. Schema models expose Type and Encoded representations and reusable effectful parsers. Accessed 2026-10-06.
- rat-stack contributors. 2026. Shared capability contracts.. rat-stack. Contract schemas model input, output, failures, records, and literal alternatives. Accessed 2026-10-06.
- rat-stack contributors. 2026. Code-mode projection.. rat-stack. The invoker decodes input before dispatch and encodes declared outputs and failures. Accessed 2026-10-06.
- rat-stack contributors. 2026. Interest application contract.. rat-stack. Contact consent and sharing consent remain separate fields. Accessed 2026-10-06.
- rat-stack contributors. 2026. Abuse score schemas.. rat-stack. The verdict type derives from a schema with a finite bounded score. Accessed 2026-10-06.
- Langton, Kit. 2026. Data Modeling. Effect Solutions.. Kit Langton. Topic framing for records, alternatives, and schema-backed domain values; no chess example is copied. Accessed 2026-10-06.
Last changed 2026-10-18 in e5c3077. Source on GitHub. Change log.
Linked from
- add-a-feature-flag. Declare a typed feature flag, its scoped evidence ladder, approval roles, removal date, and durable ledger adapter.
A stable name and JSON-encoded value schema.¶
- Agent guide. An Effect stack so pure (aspirational) Kit Langton will blush.
Schemas define the boundary — Define accepted data with Schema, decode unknown input before dispatch, and encode results through the declared contract.
- CAFE all stars. Public profiles of people and channels who build with Cloudflare, Alchemy, Foldkit and Effect, served by five read-only capabilities.
The content build decodes it with the CafePerson schema in packages/core/src/cafe.ts.
- CAFE names the Cloudflare, Alchemy, Foldkit and Effect stack. CAFE is a named stack: Cloudflare runs the app, Alchemy declares it, Foldkit draws the UI, and Effect does the typed work.
Recipe variants are typed by Effect Schema.¶
- Change log. What changed in the files served here, newest first.
Schemas define the boundary — edited: docs: refresh XState excerpts and peer evidence
- Code snippets quote a pinned source. Shipped design brief: pinned Git objects, typed diagnostics, and one build-only snippet model for both views.
Schema decoding parses unknown metadata into a CodeRequest at the boundary.
- Durability starts with a recovery record. A reading order for storage, replay, worker ownership, overload, and recovery tests.
Schemas define the boundary.¶
- Effect basics. An Effect describes work, expected failures, and required services before a runtime executes it.
Schemas define the boundary: define and decode accepted data.¶
- Effect keeps the surfaces on one contract. Schema owns values, projections build interfaces, and Layers supply implementations.
Schemas define the boundary: decode unknown values and keep domain refusals typed.¶
- Errors are part of the interface. An author error needs a location, the rejected input, and a repair.
Use schema decoding to reject invalid input at the boundary.
- Feature flags. Typed feature flags with owners, removal dates, and stable subject rollouts.
A flag declares its name, schema, default, owner, purpose, removal date, and evidence ladder.¶
- Flags climb on evidence. A flag ladder connects each rollout step to scoped measurements, approval, and a durable receipt.
The child’s readScope schema defines the flag’s scope.
- Full agent guide. An Effect stack so pure (aspirational) Kit Langton will blush.
- Handle expected failures without hiding defects. Declare expected failures, preserve their context, and recover by tag without turning crashes into successful outcomes.
See also: schemas, author-facing diagnostics, independent failures, and lifecycles.
- HTTP success needs a status check and a decoder. Supply the client, check the response status, decode accepted data, and name failures at the adapter boundary.
schemaBodyJson handles JSON parsing and schema decoding.
- Old events must still decode. Retained data needs compatibility rules before recovery depends on it.
Connect this to the existing rat-stack guidance.¶
- onboard-a-list. Analyze or migrate an email list. Measure sanitation rules, preserve stops, choose a cohort, and verify an authorized import or sending cutover.
Decode policy data with Effect Schema.
- One capability, every surface. A schema-typed contract and one handler feed every interface rat-stack keeps.
Michael Arnaldi demonstrates Schema decoding request input and encoding a frontend-safe result while preserving its output type.
- One schema, three surfaces. A capability contract feeds CLI, HTTP, and MCP; OpenAPI is generated output, not their input.
ts derives flags or positional inputs, schema decoding, and the command handler.¶
- OpenAPI describes the refusal too. The generated HTTP contract declares inputs, outputs, and the bodyless 400 returned when decoding fails.
See schema-driven development for that boundary.
- Rat Stack lore | rat-stack. Short, source-grounded notes on the ideas and decisions behind rat-stack.
Schemas define the boundary — Define accepted data with Schema, decode unknown input before dispatch, and encode results through the declared contract.
- Replay needs stable inputs. Historical processing must not silently depend on today’s clock or external decisions.
Connect this to the existing rat-stack guidance.¶
- Shared schemas need a transition period. Keep old and new representations usable while consumers migrate.
A shared schema change needs time for consumers to move.
- Source change history (log.md). The generated change log as Markdown.
Schemas define the boundary — edited: docs: refresh XState excerpts and peer evidence
- 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.
Decode at boundaries with Schema.¶
Unlinked mentions (42)
- add-a-capability → Schema defines accepted values and their runtime checks.
- add-a-feature-flag → A child-supplied readScope schema.
- add-a-lifecycle-machine → Schema defines accepted values and their runtime checks.¶
- add-a-store → Schema defines accepted values and their runtime checks.¶
- Agent rules for rat-stack (AGENTS.md) → local directly, run pnpm env:check after schema edits
- Analytics → Default: persistent in the site schema¶
- Auth → A session whose user id fails the person-id schema check also fails as Unauthenticated.¶
- Build and run rat-stack (README.md) → The host validates the input schema and runs the same handler used by every other surface.
- CAFE names the Cloudflare, Alchemy, Foldkit and Effect stack → The dials are an Effect Schema.¶
- Capabilities → Schema describes accepted values, their TypeScript types, and the rules for checking and converting them at runtime.¶
- Capture first, shape later → Events that do not match a structured stream’s schema “are accepted during ingestion but will be dropped during processing,” the docs say.
- Cartridges → ts declares the D1 schema and database.¶
- Code snippets quote a pinned source → Collect: Walk Markdown syntax-tree code nodes; scan metadata; Schema-decode requests and source locations.¶
- Configuration is a supplied, validated dependency → Schema defines accepted values and checks data at runtime.¶
- Database → Schema describes accepted values and their runtime checks.¶
- Devtools → A schema defines the accepted values.¶
- durability → “many refactorings require you to run both the original and new versions of the schema in parallel during a transition period that is long enough to allow any applications accessing that portion of the schema time to be redeployed.”¶
- Effect + Alchemy peer patterns → One schema-derived contract carries payloads and typed failures across the wire.
- Effect + Alchemy peers → Why this tier: Statechart schema conversion on XState 6 is a relevant typed-machine seam; not yet studied.
- Effect 4 study: September 2026 → Why it matters to us: Schema-first state machines native to Effect.
- Effect keeps the surfaces on one contract → An Effect Schema defines accepted values and provides types and runtime checks.
- Effect Meetup SF 2023: Why Effect? → A Remix demo contrasts manually added logs, metrics, and traces and nested error handling with Effect context, Schema, spans, metrics, and retry policies.
- Feature flags → A child schema defines it; the default is global.¶
- HTTP success needs a status check and a decoder → Schema defines accepted values and checks data at runtime.
- Interest signup → Set INTEREST_OPERATOR_TOKEN through the local environment schema.
- Learn mode presents concepts at useful depths → Effect Schema describes accepted values and their runtime checks.
- learn-rat-stack → Schema defines accepted values and their runtime checks.¶
- Lifecycles are machines → createEffectLogic defines an Effect-backed side effect with an input schema.
- Lint and type escape ledger (debt.md) → Reason: Capability failures arrive erased at this schema-decoding boundary.
- MCP is another surface → Input JSON Schema.¶
- One capability, every surface → Effect Schema provides types and runtime checks for these values.
- One schema, three surfaces → Effect Schema supplies types and runtime checks for these values.¶
- OpenAPI describes the refusal too → A declared failure defaults to 422 unless its schema names another HTTP status.
- Production-grade TypeScript → He demonstrates Effect context, Schema, spans, metrics, and retry policies in a Remix application.
- Property-based testing → The same schema defines the capability’s contract and generates its test inputs.
- rat-stack → Effect Schema defines and validates the data each operation accepts and returns.
- Schema projections: 2026-09-18 history → One Effect Schema definition can feed a CLI, REST API, MCP server, and code mode.
- Structure an Effect codebase by domain → Schema-backed boundaries: Capability contracts and derived interface projections¶
- Tests prove behavior through supplied services → schema derives input generators from Schema.
- Trace operations where they mean something → The fixture’s transport decodes outbound JSON through a small Schema.
- uncomplect → Schema: A definition of accepted values that provides TypeScript types and runtime checks.¶
- write-a-wiki-page → A schema defines accepted values and their runtime checks.