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"]);
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 three 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: (error) =>
Effect.succeed(invokeFailure("InvalidInput", error.message)),
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 tests18 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 refusal36.¶
Effect idiom and house rule
- Schema defines runtime decoding, encoding, and the associated TypeScript types.¶
- In rat-stack, one capability contract21 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 surfaces23, OpenAPI refusals15, services16, 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-07 in f1a00f2. Source on GitHub. Change log.
Linked from
- 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 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: feat(learn): teach cards 63 to 82 with plain lines, diagrams and snippets
- 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.
- 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, and removal date.¶
- 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.
- 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.
- Source change history (log.md). The generated change log as Markdown.
Schemas define the boundary — edited: feat(learn): teach cards 63 to 82 with plain lines, diagrams and snippets
- 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 (36)
- add-a-capability → Schema defines accepted values and their runtime checks.
- 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
- 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 → prop accept Schema or Arbitrary inputs.¶
- 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.¶
- Effect + Alchemy peer patterns → One schema-derived contract carries payloads and typed failures across the wire.
- Effect + Alchemy peers → statelyai/schema, main, checked 2026-10-09: package.json, pnpm-lock.yaml, README.md.
- Effect 4 study: September 2026 → PR #5687 merged 2026-09-15; #5691 added Effect Schema support.
- 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.
- 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 → fromEffect defines an Effect-backed side effect with an input schema.
- 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.
- 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 → Decode with Effect Schema at the boundary.
- write-a-wiki-page → A schema defines accepted values and their runtime checks.