Apollo HTTP Data Source
apollo-datasource-http is an optimized HTTP data source for Apollo Server, designed to enhance performance when fetching JSON data from REST APIs. Currently at version 0.21.0, it is actively developed with a frequent release cadence, though it explicitly warns that releases are pre-1.0 and may introduce breaking changes. Its key differentiators include leveraging the high-performance Undici HTTP client (claiming up to 60% faster than `apollo-datasource-rest`), integrated request deduplication via LRU caching, configurable request caching with TTL, and `stale-if-error` capabilities. It also supports `AbortController` for manual request cancellation and integrates with Apollo Cache Storage backends for advanced caching strategies. This data source aims to provide a robust and efficient solution for connecting Apollo Server to external HTTP services, offering fine-grained control over request lifecycle and caching behavior through a hook-based API.
Common errors
-
Error: Cannot find module 'apollo-datasource-http'
cause The `apollo-datasource-http` package has not been installed or is not resolvable in the current environment.fixRun `npm install apollo-datasource-http` or `yarn add apollo-datasource-http` to install the package. -
Error: dataSources must be a function which returns an object or a Promise which resolves to an object.
cause The `dataSources` property in the `ApolloServer` constructor was not provided as a function that returns the data source instances.fixEnsure your `dataSources` configuration is a function, e.g., `dataSources: () => ({ moviesAPI: new MoviesAPI(baseURL, pool) })`. -
npm ERR! ERESOLVE unable to resolve dependency tree (or similar peer dependency warning for 'graphql')
cause Your project's `graphql` version conflicts with the peer dependency requirement of `apollo-datasource-http`.fixUpdate your `graphql` package to a compatible version (e.g., `npm install graphql@16`) or adjust your dependency resolution strategy to satisfy the `^15.3.0 || ^16.0.0` range.
Warnings
- breaking This package is explicitly declared as pre-1.0 according to SemVer. This means that minor versions (e.g., 0.x.0 to 0.y.0) may introduce breaking changes without prior warning.
- gotcha To achieve the advertised performance benefits, you must explicitly initialize and pass an `undici.Pool` instance to the `HTTPDataSource` constructor. Failing to do so will result in each request creating a new Undici client, negating performance optimizations.
- breaking Version 0.18.0 introduced significant updates for compatibility with Apollo Server 3 and GraphQL 16. Older versions of Apollo Server or GraphQL might not function correctly with `apollo-datasource-http` versions 0.18.0 or newer.
Install
-
npm install apollo-datasource-http -
yarn add apollo-datasource-http -
pnpm add apollo-datasource-http
Imports
- HTTPDataSource
const HTTPDataSource = require('apollo-datasource-http')import { HTTPDataSource } from 'apollo-datasource-http' - Pool
import { Pool } from 'apollo-datasource-http'import { Pool } from 'undici'
Quickstart
import { ApolloServer } from '@apollo/server';
import { startStandaloneServer } from '@apollo/server/standalone';
import { Pool } from 'undici';
import { HTTPDataSource } from 'apollo-datasource-http';
const typeDefs = `#graphql
type Movie {
id: ID!
name: String
}
type Query {
movie(id: ID!): Movie
}
type Mutation {
createMovie(name: String!): Movie
}
`;
const baseURL = 'https://movies-api.example.com'; // Replace with your actual API base URL
const pool = new Pool(baseURL);
class MoviesAPI extends HTTPDataSource {
constructor(baseURL: string, pool: Pool) {
super(baseURL, { pool });
}
async createMovie(name: string) {
return this.post('/movies', {
body: { name }
});
}
async getMovie(id: string) {
return this.get(`/movies/${id}`, {
context: { tracingName: 'getMovie' },
requestCache: {
maxTtl: 10 * 60, // 10min, will respond for 10min with the cached result
maxTtlIfError: 30 * 60 // 30min, will respond with cached response in case of error
}
});
}
}
const resolvers = {
Query: {
movie: async (_, { id }, { dataSources }) => {
return dataSources.moviesAPI.getMovie(id);
}
},
Mutation: {
createMovie: async (_, { name }, { dataSources }) => {
return dataSources.moviesAPI.createMovie(name);
}
}
};
const server = new ApolloServer({
typeDefs,
resolvers,
});
startStandaloneServer(server, {
listen: { port: 4000 },
context: async ({ req, res }) => ({
dataSources: {
moviesAPI: new MoviesAPI(baseURL, pool),
},
}),
}).then(({ url }) => {
console.log(`🚀 Server ready at ${url}`);
});