Introspection
GraphQL introspection: querying the schema itself. Useful for tooling, dangerous on public APIs.
GraphQL — introspection
EXAMPLE
# ===== What introspection is =====
# GraphQL ships with a meta-query that returns the schema:
{
__schema {
types {
name
kind
fields {
name
type { name kind }
}
}
}
}
# Powers:
# - GraphiQL / Apollo Studio explorers
# - Codegen tools (graphql-codegen)
# - IDE plugins (VS Code GraphQL)
# - Client cache normalisation
# ===== Useful introspection queries =====
# All type names:
{ __schema { types { name } } }
# Specific type:
{ __type(name: "User") { name fields { name type { name } } } }
# All queries:
{ __schema { queryType { fields { name } } } }
# Directives:
{ __schema { directives { name args { name } locations } } }
# ===== Tooling =====
# graphql-codegen extracts schema + queries for typed clients:
# codegen.yml
schema: http://localhost:4000/graphql
documents: 'src/**/*.graphql'
generates:
src/generated/graphql.ts:
plugins: [typescript, typescript-operations, typescript-react-apollo]
# ===== Security concerns =====
# Public APIs that expose introspection give attackers:
# - Full schema (every type, field, query, mutation)
# - Argument types (validation hints)
# - Custom directive locations
# Common decision: ENABLE introspection in dev / staging; DISABLE in production.
# ===== Disable in production =====
# Apollo Server:
import { ApolloServer } from '@apollo/server';
const server = new ApolloServer({
typeDefs,
resolvers,
introspection: process.env.NODE_ENV !== 'production',
});
# Yoga:
import { createYoga } from 'graphql-yoga';
const yoga = createYoga({
schema,
graphiql: false,
plugins: [
process.env.NODE_ENV === 'production' && {
onValidate({ document }) {
// Reject queries that touch __schema or __type
},
},
].filter(Boolean),
});
# Or use graphql-disable-introspection:
import { disableIntrospection } from '@envelop/disable-introspection';
# ===== Alternative: persisted queries =====
# If you use persisted operations (allowlist), introspection-via-arbitrary-query becomes
# moot because clients can ONLY send allowlisted queries.
# ===== Tooling without runtime introspection =====
# Even with introspection disabled in prod, your build can dump the schema:
npx get-graphql-schema http://localhost:4000/graphql > schema.graphql
# Ship the schema with the codegen pipeline; don't query prod.
# ===== Patterns =====
# - Enable in dev / staging
# - Disable in production (or restrict to authenticated admin)
# - Persisted operations for public APIs
# - Schema export in build for codegen
# - Schema registry (Apollo Studio / GraphOS) for cross-service composition
# ===== Pitfalls =====
# - Production introspection leaks the entire API surface
# - Tools assume introspection always available -> fail in prod
# - Disabling introspection without persisted ops -> arbitrary queries still allowed
# - Forgetting to publish schema to registry on deploy
Why it matters
Introspection is the schema-query mechanism that powers tooling. Enable in dev, disable in prod (or guard with auth + persisted operations). Use schema export + registry for codegen and cross-service composition; never query prod for the schema.
Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.
Discussion
Loading…