Custom Scalars
You'll learn to
- -Define a custom GraphQL scalar with serialize/parseValue/parseLiteral logic for a domain-specific type
- -Know when a custom scalar is the right tool versus just using String with documented formatting conventions
GraphQL's built-in scalars (`Int`, `Float`, `String`, `Boolean`, `ID`) don't cover every kind of value an API needs to represent precisely - a date, a URL, or an email address could technically be sent as a `String`, but that throws away the opportunity to validate and document the value's actual shape at the schema level.
Defining a Custom Scalar
scalar DateTime
type Order {
id: ID!
placedAt: DateTime!
}from datetime import datetime
class DateTimeScalar:
def serialize(self, value: datetime) -> str:
# Python datetime -> ISO 8601 string, going OUT to the client
return value.isoformat() + "Z"
def parse_value(self, value: str) -> datetime:
# incoming variable value -> Python datetime, going IN from the client
return datetime.fromisoformat(value.rstrip("Z"))
def parse_literal(self, node) -> datetime:
# incoming inline literal in the query string itself
return datetime.fromisoformat(node.value.rstrip("Z"))A scalar needs three functions: `serialize` (internal representation to wire format, for responses), `parseValue` (wire format to internal representation, for variables), and `parseLiteral` (wire format to internal representation, for values written directly in the query string). Once defined, `DateTime` behaves like any built-in scalar in the schema - but with validation and consistent formatting enforced centrally, in one place, rather than every resolver that touches a date reimplementing its own parsing and formatting.
When a Custom Scalar Is Worth It
- -The value has a well-defined, validatable format (dates, URLs, email addresses, currency amounts) where "is this actually valid" is a real, checkable question - not just any string.
- -The same kind of value appears across many fields and types, making centralized validation and formatting logic worth the setup cost.
- -Clients benefit from knowing the field is specifically a `DateTime` rather than an opaque `String`, for their own tooling (client-side type generation, form validation) to take advantage of.
For a one-off, rarely-used field where the "format" is really just documentation ("this string happens to look like X"), a plain `String` with a clear description in the schema is often simpler and perfectly adequate - custom scalars earn their setup cost when validation and reuse genuinely matter, not as a default for every field that isn't a plain number or boolean.
A custom scalar's validation runs automatically as part of GraphQL's own request parsing, before any resolver code executes - an invalid `DateTime` value is rejected by the framework itself, not silently accepted and passed through to a resolver that might not check it.
Interview Signal is part of Pro
See a real weak answer next to a real strong one for this exact topic.
Quiz is part of Pro
Test what you just read with a short quiz, and bank the XP.
Design Custom Scalars Lab in the API Design Lab's GraphQL Mastery act.