Comprehensive plugin system providing extensible hooks into the GraphQL request lifecycle. Apollo Server includes 12+ built-in plugins for metrics, caching, landing pages, and Apollo Studio integration.
Base interface for creating custom plugins with server and request lifecycle hooks.
/**
* Plugin interface for extending Apollo Server functionality
*/
interface ApolloServerPlugin<TContext = BaseContext> {
/**
* Server startup hook - called when server starts
*/
serverWillStart?(service: GraphQLServiceContext): Promise<GraphQLServerListener | void>;
/**
* Request lifecycle hook - called for each GraphQL request
*/
requestDidStart?(requestContext: GraphQLRequestContext<TContext>): Promise<GraphQLRequestListener<TContext> | void>;
}
/**
* Server lifecycle listener
*/
interface GraphQLServerListener {
serverWillStop?(): Promise<void>;
}
/**
* Request lifecycle listener with hooks for each phase
*/
interface GraphQLRequestListener<TContext = BaseContext> {
requestDidStart?(requestContext: GraphQLRequestContext<TContext>): Promise<void>;
didResolveSource?(requestContext: GraphQLRequestContextDidResolveSource<TContext>): Promise<void>;
parsingDidStart?(requestContext: GraphQLRequestContextParsingDidStart<TContext>): Promise<void>;
validationDidStart?(requestContext: GraphQLRequestContextValidationDidStart<TContext>): Promise<void>;
didResolveOperation?(requestContext: GraphQLRequestContextDidResolveOperation<TContext>): Promise<void>;
didEncounterErrors?(requestContext: GraphQLRequestContextDidEncounterErrors<TContext>): Promise<void>;
executionDidStart?(requestContext: GraphQLRequestContextExecutionDidStart<TContext>): Promise<GraphQLRequestExecutionListener<TContext> | void>;
willSendResponse?(requestContext: GraphQLRequestContextWillSendResponse<TContext>): Promise<void>;
}Reports GraphQL operation metrics to Apollo Studio for performance monitoring and analytics.
/**
* Enable usage reporting to Apollo Studio
* @param options - Configuration options for usage reporting
* @returns Plugin instance
*/
function ApolloServerPluginUsageReporting<TContext>(
options?: ApolloServerPluginUsageReportingOptions<TContext>
): ApolloServerPlugin<TContext>;
/**
* Disable usage reporting (explicit opt-out)
* @returns Plugin instance that disables usage reporting
*/
function ApolloServerPluginUsageReportingDisabled(): ApolloServerPlugin;
/**
* Usage reporting configuration options
*/
interface ApolloServerPluginUsageReportingOptions<TContext> {
/** Apollo API key (defaults to APOLLO_KEY env var) */
apiKey?: string;
/** Graph ID (defaults to APOLLO_GRAPH_ID env var) */
graphId?: string;
/** Graph variant (defaults to APOLLO_GRAPH_VARIANT env var) */
graphVariant?: string;
/** Send variable values configuration */
sendVariableValues?: SendValuesBaseOptions;
/** Send headers configuration */
sendHeaders?: SendValuesBaseOptions;
/** Generate client info function */
generateClientInfo?: GenerateClientInfo<TContext>;
/** Send errors to Apollo Studio */
sendErrorsToStudio?: boolean;
/** Send reports immediately (for testing) */
sendReportsImmediately?: boolean;
/** Request agent for HTTP requests */
requestAgent?: Agent;
/** Maximum report size before splitting */
maxReportSizeBytes?: number;
}Reports GraphQL schema changes to Apollo Studio for schema registry and governance.
/**
* Enable schema reporting to Apollo Studio
* @param options - Configuration options for schema reporting
* @returns Plugin instance
*/
function ApolloServerPluginSchemaReporting(
options?: ApolloServerPluginSchemaReportingOptions
): ApolloServerPlugin;
/**
* Schema reporting configuration options
*/
interface ApolloServerPluginSchemaReportingOptions {
/** Apollo API key (defaults to APOLLO_KEY env var) */
apiKey?: string;
/** Graph ID (defaults to APOLLO_GRAPH_ID env var) */
graphId?: string;
/** Graph variant (defaults to APOLLO_GRAPH_VARIANT env var) */
graphVariant?: string;
/** Override automatic schema hash calculation */
overrideReportedSchema?: string;
/** Initial delay before first report */
initialDelayMaxMs?: number;
/** Override endpoint URL */
endpointUrl?: string;
}Adds Apollo tracing data directly to GraphQL responses for performance analysis.
/**
* Enable inline tracing in GraphQL responses
* @param options - Configuration options for inline tracing
* @returns Plugin instance
*/
function ApolloServerPluginInlineTrace(
options?: ApolloServerPluginInlineTraceOptions
): ApolloServerPlugin;
/**
* Disable inline tracing (explicit opt-out)
* @returns Plugin instance that disables inline tracing
*/
function ApolloServerPluginInlineTraceDisabled(): ApolloServerPlugin;
/**
* Inline trace configuration options
*/
interface ApolloServerPluginInlineTraceOptions {
/** Function to determine if request should include tracing */
includeTrace?: (requestContext: GraphQLRequestContext) => boolean;
/** Rewrite error messages in traces */
rewriteError?: (error: GraphQLError) => GraphQLError | null;
}Adds HTTP cache control headers based on GraphQL schema cache hints.
/**
* Enable cache control based on schema directives
* @param options - Configuration options for cache control
* @returns Plugin instance
*/
function ApolloServerPluginCacheControl(
options?: ApolloServerPluginCacheControlOptions
): ApolloServerPlugin;
/**
* Disable cache control (explicit opt-out)
* @returns Plugin instance that disables cache control
*/
function ApolloServerPluginCacheControlDisabled(): ApolloServerPlugin;
/**
* Cache control configuration options
*/
interface ApolloServerPluginCacheControlOptions {
/** Default max age in seconds */
defaultMaxAge?: number;
/** Calculate HTTP cache control header */
calculateHttpCacheControlHeader?: boolean;
/** Strip formatting from cached documents */
stripFormattedExtensions?: boolean;
}Handles graceful shutdown by draining HTTP connections before server termination.
/**
* Enable graceful HTTP server shutdown
* @param options - Configuration options for server draining
* @returns Plugin instance
*/
function ApolloServerPluginDrainHttpServer(
options: ApolloServerPluginDrainHttpServerOptions
): ApolloServerPlugin;
/**
* HTTP server drain configuration options
*/
interface ApolloServerPluginDrainHttpServerOptions {
/** HTTP server instance to drain */
httpServer: http.Server;
/** Grace period in milliseconds for shutdown */
stopGracePeriodMillis?: number;
}Disables the default Apollo Server landing page.
/**
* Disable Apollo Server landing page
* @returns Plugin instance that disables landing page
*/
function ApolloServerPluginLandingPageDisabled(): ApolloServerPlugin;Provides a local development landing page with GraphQL Playground integration.
/**
* Enable local development landing page
* @param options - Configuration options for local landing page
* @returns Plugin instance
*/
function ApolloServerPluginLandingPageLocalDefault(
options?: ApolloServerPluginLandingPageLocalDefaultOptions
): ApolloServerPlugin;
/**
* Local landing page configuration options
*/
interface ApolloServerPluginLandingPageLocalDefaultOptions extends ApolloServerPluginLandingPageDefaultBaseOptions {
/** Enable embedded GraphQL Playground */
embed?: boolean;
/** Include cookies in Playground requests */
includeCookies?: boolean;
}Provides a production-ready landing page optimized for deployed environments.
/**
* Enable production landing page
* @param options - Configuration options for production landing page
* @returns Plugin instance
*/
function ApolloServerPluginLandingPageProductionDefault(
options?: ApolloServerPluginLandingPageProductionDefaultOptions
): ApolloServerPlugin;
/**
* Production landing page configuration options
*/
interface ApolloServerPluginLandingPageProductionDefaultOptions extends ApolloServerPluginLandingPageDefaultBaseOptions {
/** Apollo Studio graph reference */
graphRef?: string;
/** Include cookies in Apollo Studio Explorer */
includeCookies?: boolean;
}
/**
* Base landing page configuration options
*/
interface ApolloServerPluginLandingPageDefaultBaseOptions {
/** Document title */
title?: string;
/** Footer text */
footer?: string;
/** Version information */
version?: string;
}Provides the classic GraphQL Playground interface as a landing page.
/**
* Enable GraphQL Playground landing page
* @param options - Configuration options for GraphQL Playground
* @returns Plugin instance
*/
function ApolloServerPluginLandingPageGraphQLPlayground(
options?: ApolloServerPluginLandingPageGraphQLPlaygroundOptions
): ApolloServerPlugin;
/**
* GraphQL Playground configuration options
*/
interface ApolloServerPluginLandingPageGraphQLPlaygroundOptions {
/** Playground title */
title?: string;
/** Version string */
version?: string;
/** Playground settings */
settings?: {
'editor.theme'?: 'dark' | 'light';
'editor.fontSize'?: number;
'editor.fontFamily'?: string;
'editor.cursorShape'?: 'line' | 'block' | 'underline';
'prettier.useTabs'?: boolean;
'prettier.tabWidth'?: number;
'request.credentials'?: 'omit' | 'include' | 'same-origin';
[key: string]: any;
};
/** Default tabs */
tabs?: Array<{
endpoint?: string;
query?: string;
variables?: string;
responses?: string[];
headers?: Record<string, string>;
}>;
/** Playground CDN URL */
cdnUrl?: string;
/** Custom favicon URL */
faviconUrl?: string;
/** Workspace name */
workspaceName?: string;
}import {
ApolloServer,
ApolloServerPluginUsageReporting,
ApolloServerPluginCacheControl,
ApolloServerPluginDrainHttpServer,
ApolloServerPluginLandingPageLocalDefault,
} from 'apollo-server';
import http from 'http';
// Create HTTP server for drain plugin
const httpServer = http.createServer();
const server = new ApolloServer({
typeDefs,
resolvers,
plugins: [
// Apollo Studio integration
ApolloServerPluginUsageReporting({
sendVariableValues: { all: true },
sendHeaders: { exceptNames: ['authorization'] },
}),
// Cache control
ApolloServerPluginCacheControl({
defaultMaxAge: 300, // 5 minutes
calculateHttpCacheControlHeader: true,
}),
// Graceful shutdown
ApolloServerPluginDrainHttpServer({
httpServer,
stopGracePeriodMillis: 10000,
}),
// Development landing page
ApolloServerPluginLandingPageLocalDefault({
embed: true,
includeCookies: true,
}),
],
});
// Apply server to HTTP server for drain plugin
httpServer.on('request', app);Creating custom plugins for specific application needs.
// Example: Request logging plugin
const requestLoggingPlugin: ApolloServerPlugin = {
requestDidStart() {
return {
willSendResponse(requestContext) {
console.log(
`GraphQL request: ${requestContext.request.operationName || 'Anonymous'} ` +
`executed in ${Date.now() - requestContext.request.http?.startTime}ms`
);
},
};
},
};
// Example: Authentication plugin
const authenticationPlugin: ApolloServerPlugin = {
requestDidStart() {
return {
didResolveOperation(requestContext) {
if (requestContext.operationName === 'IntrospectionQuery') {
return; // Allow introspection
}
if (!requestContext.context.user) {
throw new AuthenticationError('Authentication required');
}
},
};
},
};
const server = new ApolloServer({
typeDefs,
resolvers,
plugins: [
requestLoggingPlugin,
authenticationPlugin,
],
});