GraphQL is a query language for APIs and a runtime for executing those queries with your existing data. It was developed by Facebook and released as an open-source project in 2015.
DOCS: https://www.apollographql.com/docs/apollo-server/getting-started
GraphQL is a query language for APIs and a runtime for executing those queries with your existing data.
- Developed by Facebook in 2012 and open-sourced in 2015.
- Allows clients to request only the data they need.
- Single endpoint (
/graphql) instead of multiple REST endpoints.
- Efficient Data Fetching: Prevents over-fetching or under-fetching of data.
- Strongly Typed Schema: Defined with
type,query,mutation, etc. - Better Developer Experience: Real-time introspection and auto-documentation.
- Single Endpoint: All interactions happen through a single API route.
| Feature | GraphQL | REST |
|---|---|---|
| Endpoint | Single (/graphql) |
Multiple (/users, /posts, etc.) |
| Data Fetching | Precise, client-driven | Fixed, server-driven |
| Versioning | Not required | Often requires /v1, /v2, etc. |
| Data Structure | Custom per query | Fixed per route |
type User {
id: ID!
name: String!
email: String!
}
type Query {
users: [User]
user(id: ID!): User
}
type Mutation {
addUser(name: String!, email: String!): User
}const resolvers = {
Query: {
users: () => db('users'),
user: (_, args) => db('users').where('id', args.id).first(),
},
Mutation: {
addUser: (_, { name, email }) =>
db('users').insert({ name, email }).returning('*').then(res => res[0])
}
};dbhere refers to a Knex.js instance connected to a SQL database.
- Apollo Server: A popular GraphQL server implementation.
- GraphQL Playground: Interactive IDE to test GraphQL queries.
- Knex.js: SQL query builder that works well with GraphQL resolvers.
query {
user(id: 1) {
name
email
}
}mutation {
addUser(name: "Lucas", email: "lucas@example.com") {
id
name
}
}- GraphQL.org Docs
- Apollo GraphQL Tutorials
- Practice using tools like:
| Concept | Description |
|---|---|
| Endpoint | URL path where the client sends requests |
| HTTP Methods | GET, POST, PUT, PATCH, DELETE |
| Request/Response | Communication between client and server |
| Status Codes | 200, 404, 500, etc. |
| Headers/Params | Extra data passed with requests/responses |
| Body | Main content for POST/PUT requests (JSON) |
| Authentication | API keys, tokens, OAuth, etc. |
| Rate Limiting | Controls usage |
- REST (resource-based, stateless)
- GraphQL (single endpoint, flexible queries)
- SOAP (XML, strict, legacy)
- gRPC (binary, fast, uses
.protofiles)
- API Key
- Basic Auth
- OAuth2
- JWT (JSON Web Token)
- Swagger/OpenAPI, GraphiQL
- Postman, cURL, Insomnia
- Client-specified queries: Clients can request exactly the data they need.
- Single endpoint: All operations go through one endpoint (
/graphql), unlike REST which has multiple. - Strongly typed schema: Every GraphQL API is backed by a schema defining types and operations.
- Real-time support: Subscriptions allow real-time updates over WebSockets.
- Hierarchical structure: Queries mirror the shape of the result.
- Efficient data fetching: Prevents over-fetching and under-fetching by letting clients choose fields.
- Introspection: You can query the schema for available types and fields.
- Tooling: Tools like GraphiQL, Apollo DevTools, and Playground enhance developer experience.
GraphQL has introspection built in β it lets you ask:
What queries/mutations are available?
What fields do they return?
What types and enums exist?
What arguments do fields take?
Example query:
{
__schema {
types {
name
}
}
}const query = \`
{
country(code: "IN") {
name
capital
currency
}
}
\`;
fetch("https://countries.trevorblades.com/", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({ query })
})
.then(res => res.json())
.then(data => {
console.log(data.data.country);
})
.catch(err => {
console.error("GraphQL request failed", err);
});npm install @apollo/client graphqlSetup:
import { ApolloClient, InMemoryCache, ApolloProvider, gql, useQuery } from '@apollo/client';
const client = new ApolloClient({
uri: 'https://countries.trevorblades.com/',
cache: new InMemoryCache()
});Component:
const GET_COUNTRY = gql\`
query {
country(code: "IN") {
name
capital
currency
}
}
\`;
function CountryInfo() {
const { loading, error, data } = useQuery(GET_COUNTRY);
if (loading) return <p>Loading...</p>;
if (error) return <p>Error: {error.message}</p>;
return (
<div>
<h3>{data.country.name}</h3>
<p>Capital: {data.country.capital}</p>
<p>Currency: {data.country.currency}</p>
</div>
);
}Wrap app with ApolloProvider:
<ApolloProvider client={client}>
<CountryInfo />
</ApolloProvider>