A complete introduction to Apollo, the GraphQL toolkit
By Flavio Copes
Learn how to use current Apollo Client with React and Apollo Server to query, cache, and serve a GraphQL API, including authentication basics.

Apollo is a collection of tools for working with GraphQL.
The two pieces you are most likely to use are:
- Apollo Client, which sends GraphQL operations from an application and caches the results
- Apollo Server, which runs a GraphQL API in Node.js
You can use either one independently. Apollo Client can talk to any standards-compliant GraphQL server, and Apollo Server can serve any GraphQL client.
Older tutorials use packages such as apollo-boost, react-apollo, apollo-client, and apollo-server. Those packages are obsolete. Current projects use the scoped @apollo/client and @apollo/server packages.
What does Apollo Client do?
Apollo Client sends queries, mutations, and subscriptions to a GraphQL API.
It also stores results in a normalized in-memory cache. When two query results describe the same object, Apollo can identify that object and update every part of the interface that uses it.
Apollo Client is not limited to React, but this guide uses the official React integration.
How do you install Apollo Client?
In a React project, install:
npm install @apollo/client graphql rxjs
graphql provides the core GraphQL parsing and execution utilities. Apollo Client uses RxJS observables internally, so rxjs is also a direct dependency.
How do you create an Apollo Client?
Create a client near your React entry point:
import {
ApolloClient,
HttpLink,
InMemoryCache
} from '@apollo/client'
const client = new ApolloClient({
link: new HttpLink({
uri: '/graphql'
}),
cache: new InMemoryCache()
})
HttpLink sends operations over HTTP. Change /graphql to the URL of your API.
InMemoryCache stores query results for the lifetime of the page. It uses fields such as __typename and id to identify objects by default.
How do you connect Apollo Client to React?
Import ApolloProvider from the React entry point and wrap the application:
import { ApolloProvider } from '@apollo/client/react'
import { createRoot } from 'react-dom/client'
const root = createRoot(document.getElementById('root'))
root.render(
<ApolloProvider client={client}>
<App />
</ApolloProvider>
)
Components below the provider can now use Apollo’s React hooks.
How do you run a query?
Define a GraphQL document with the gql template tag:
import { gql } from '@apollo/client'
import { useQuery } from '@apollo/client/react'
const GET_BOOKS = gql`
query GetBooks {
books {
id
title
author
}
}
`
export default function Books() {
const { loading, error, data } = useQuery(GET_BOOKS)
if (loading) {
return <p>Loading...</p>
}
if (error) {
return <p>Could not load the books.</p>
}
return (
<ul>
{data.books.map((book) => (
<li key={book.id}>
{book.title} by {book.author}
</li>
))}
</ul>
)
}
useQuery() starts the operation, subscribes the component to the result, and re-renders it when the state changes.
The loading, error, and data states all matter. Do not assume that data is immediately available.
How does the cache work?
Apollo Client checks the cache before sending the same query to the network. The default fetch policy for many queries is cache-first.
You can choose another policy for a specific query:
const result = useQuery(GET_BOOKS, {
fetchPolicy: 'network-only'
})
Do this deliberately. Disabling the cache everywhere removes one of Apollo Client’s main benefits.
After a mutation, Apollo can often update existing objects automatically when the mutation returns their identifiers and changed fields. For list additions, removals, or results with unusual identifiers, you may need to update the cache or refetch a query.
How do you authenticate a request?
The safest setup depends on the application.
If the server uses a secure session cookie, include credentials in the HTTP link:
const httpLink = new HttpLink({
uri: '/graphql',
credentials: 'include'
})
The server must configure CORS correctly when the client and API use different origins. Cookie-authenticated mutation requests also need CSRF protection.
For bearer-token authentication, add an authorization link before the HTTP link:
import {
ApolloClient,
HttpLink,
InMemoryCache
} from '@apollo/client'
import { SetContextLink } from '@apollo/client/link/context'
const httpLink = new HttpLink({
uri: '/graphql'
})
const authLink = new SetContextLink(({ headers }) => {
const token = getAccessToken()
return {
headers: {
...headers,
authorization: token ? `Bearer ${token}` : ''
}
}
})
const client = new ApolloClient({
link: authLink.concat(httpLink),
cache: new InMemoryCache()
})
getAccessToken() is application-specific. Do not put a server API key, private GitHub token, or other long-lived secret in browser code. Anyone can inspect a browser bundle.
Also remember that authentication answers “who is this?” Authorization still has to be enforced by the server for every protected operation and object.
What does Apollo Server do?
Apollo Server runs a GraphQL API.
You provide:
- A schema containing GraphQL type definitions
- Resolver functions that return the data for fields
- Optional context shared by the resolvers for one operation
- Plugins and integration settings
Apollo Server can read from databases, REST APIs, queues, files, or other GraphQL services. GraphQL does not decide where your data lives.
How do you install Apollo Server?
Create a Node.js project and install:
npm install @apollo/server graphql
The following JavaScript example uses ES modules. Save it as server.mjs, or set "type": "module" in package.json.
How do you create a small GraphQL server?
import { ApolloServer } from '@apollo/server'
import {
startStandaloneServer
} from '@apollo/server/standalone'
const books = [
{
id: '1',
title: 'The Hobbit',
author: 'J.R.R. Tolkien'
},
{
id: '2',
title: 'The Left Hand of Darkness',
author: 'Ursula K. Le Guin'
}
]
const typeDefs = `#graphql
type Book {
id: ID!
title: String!
author: String!
}
type Query {
books: [Book!]!
}
`
const resolvers = {
Query: {
books() {
return books
}
}
}
const server = new ApolloServer({
typeDefs,
resolvers
})
const { url } = await startStandaloneServer(server, {
listen: {
port: 4000
}
})
console.log(`Server ready at ${url}`)
Run it:
node server.mjs
Open the URL printed in the terminal. In a development setup, Apollo’s landing page can open Apollo Sandbox, where you can run this query:
query GetBooks {
books {
id
title
author
}
}
The standalone server is excellent for learning and prototypes. Apollo recommends a web-framework integration for production applications that need more control over routing, CORS, middleware, and the rest of the HTTP stack.
What is a resolver?
A resolver returns the value for one field.
Its full signature receives four arguments:
field(parent, args, contextValue, info) {
// ...
}
parentis the result from the parent fieldargscontains the GraphQL field argumentscontextValuecontains per-operation data such as the authenticated user and data sourcesinfodescribes the GraphQL operation and schema
Most resolvers only need some of these values.
How do you authenticate an Apollo Server request?
Read and verify the credential while creating the context. Put the resulting user, not the raw unverified token, in contextValue.
Then check permissions in the relevant resolver or in a shared authorization layer:
const resolvers = {
Query: {
account(parent, args, contextValue) {
if (!contextValue.user) {
throw new Error('Not authenticated')
}
return findAccount(contextValue.user.id)
}
}
}
Do not rely on hiding a field in the client. A caller can send any valid GraphQL operation directly to the server.
For public production GraphQL endpoints, also set request-size limits, timeouts, and limits on expensive operations. Keep introspection and developer landing pages aligned with your threat model.
Do you need Apollo GraphOS?
No. Apollo Client and Apollo Server work without a hosted Apollo account.
Apollo GraphOS is an optional platform for schema delivery, operation metrics, routing, and collaboration across GraphQL services. Add it when those operational features solve a real problem for your team.
Start with the current official Apollo Client guide and Apollo Server guide for version-specific details.
Related posts about graphql: