website/blog/2026-05-18-relay-21.mdx
Relay v21.0.0 brings first-party TypeScript support, modernized Flow type generation, new error handling capabilities, and experimental React Server Components support. This release contains several breaking changes -- please read the migration notes below carefully.
TypeScript users: First-party .d.ts type definitions are now shipped directly in relay-runtime and react-relay. You no longer need @types/relay-runtime from DefinitelyTyped. Node.js ESM named imports (e.g. import { fetchQuery } from 'relay-runtime') now work correctly in .mjs files. Thank you to everyone who contributed to the DefinitelyTyped type definitions over the years — your work kept the Relay TypeScript community going, and it served as a valuable reference for these first-party types.
Flow users -- action required: Generated types now use modern Flow syntax. (expr: Type) casts are replaced with (expr as Type) (requires Flow >= 0.250.0), $ReadOnlyArray becomes ReadonlyArray, mixed becomes unknown, and $NonMaybeType becomes NonNullable. After upgrading, you must re-run the Relay compiler to regenerate all artifacts.
@live_query removed: The @live_query directive has been removed. Migrate to @client_polling(interval: ...) for polling behavior, or @live for server-pushed updates.
Relay Resolvers -- new syntax required: The enable_legacy_verbose_resolver_syntax flag has been removed. The legacy verbose docblock syntax (@onType, @onInterface, @fieldName, @edgeTo) no longer works. In addition, we've replaced the generic @RelayResolver tag with more specific @relayField and @relayType tags. The Relay compiler can automatically migrate you to this new syntax via the relay-compiler codemod fix-all command. If you're not ready to migrate, you can enable the allow_legacy_relay_resolver_tag feature flag in your compiler config file.
@oneOf inputs: @oneOf input types now generate a stricter discriminated union type that only permits one property at a time, instead of an object with all optional fields. This catches bugs at compile time where multiple fields were incorrectly set simultaneously. You can opt out via oneOfType: "relaxed" in compiler config if needed.
Filename prefix no longer required: Relay no longer requires fragment, query, and mutation names to be prefixed with the name of the file in which they appear. Historically Relay was designed around Meta's internal module resolution system "Haste" which required all modules to have a globally unique filename. Relay required all fragments, queries, and mutations to be prefixed with that filename to make finding definitions easier. However, this requirement provided little value to our open source users and added significant friction, and so the restriction has been removed for non-Haste projects.
@catch expansion: @catch now works on @connection fields and client edge fields, letting you gracefully handle field errors in pagination and client-edge scenarios instead of throwing.
@alias on fragment definitions: The @alias directive now works on fragment definitions (not just inline fragments).
New compiler CLI tools: Two experimental subcommands are available: experimental-regenerate-sub-schema replaces the currently configured schema file with the portion of the provided "full schema" and experimental-compare-document-ir compares intermediate representations (IR) of documents passed and outputs selections that exists in left but not in right.
React Server Components (Experimental): A new react-relay/rsc_EXPERIMENTAL entry point provides an experimental API for fetching GraphQL in server components: serverFetchQuery for server-side data fetching, serverReadFragment for reading fragment data on the server, and serverPreloadQuery + useQueryFromServer for preloading data on the server and hydrating the client store. These APIs are experimental and are likely to change in upcoming versions.
@raw_response_type accuracy: Selections on abstract types in @raw_response_type are now correctly typed as optional when the concrete type may not implement the abstract type (PR #4775).@match fields: The compiler now properly validates and reports errors for conflicting @match fields across fragments, preventing silent runtime issues.--watch mode, including cross-project fragment crash resolution and proper detection of schema field changes.mixed to unknown (commit)query-stats subcommand for per-operation fragment usage analysis (commit)<Activity> a->b->a mutation edge case (commit)extend X { ... } instead of X { ... } (commit)react-prefer-namespace-import ESLint Rule (commit)requireCond (commit)pretty crate for document-based formatting (commit)set_remove_defined_references to remove Set contents from a given exclusionary schema (commit)arc lint --take PRETTIERJAVASCRIPT (commit)$Values to Values (commit)mixed to unknown in xplat/js (commit)$NonMaybeType) to TypeScript-style types in xplat/js (commit)$ReadOnlySet (commit)react.ref_as_prop=experimental.store_ref_in_props_but_remove_ref_in_react_element_config in fbsource (commit)Array.{includes,indexOf,lastIndexOf} in xplat (commit)FeatureFlags to align FeatureFlags::default() with Serde per-field default (#5064) (commit)experimental.natural_inference.local_object_literals.followup_fix in xplat (commit)expr_2021 -> expr (commit)incompatible-type in relay (commit)use_experimental_provider (commit)