VOOZH about

URL: https://dev.to/mohamedelmorsy/what-is-graphql-546l

⇱ What Is GraphQL? - DEV Community


You've been building REST APIs — one endpoint for users, another for posts, another for comments. The client makes three requests, stitches the data together, and half of it gets thrown away because it wasn't needed in the first place.

GraphQL was built to fix exactly that. It gives the client full control over what data it receives. One request. Exactly what you asked for. Nothing more, nothing less.


The Problem REST Couldn't Solve

Before understanding GraphQL, you need to understand the two problems that drove its creation.

Over-fetching

The server returns more data than the client needs.

GET /users/123

Response:
{
 "id": 123,
 "name": "Anne",
 "email": "anne@example.com",
 "phone": "...",
 "address": "...",
 "createdAt": "...", ← you didn't need any of this
 "updatedAt": "..." ← but the server sent it anyway
}

The client only needed name and email — but it downloaded the whole object every time.

Under-fetching

One endpoint doesn't return enough, so the client has to make multiple requests.

GET /users/123 → gets the user
GET /users/123/posts → gets their posts
GET /users/123/followers → gets their followers

Three round trips to the server just to render one screen. On a mobile network, that cost is real.

👁 GraphQL vs REST over-fetching and under-fetching

GraphQL's answer: Let the client write the query. The server returns exactly what was asked.


What Is GraphQL?

GraphQL is a query language for your API and a runtime for executing those queries. It was created by Facebook in 2012, open-sourced in 2015, and is now maintained by the GraphQL Foundation.

Unlike REST, which exposes multiple URL endpoints, GraphQL exposes a single endpoint — typically POST /graphql. The client sends a query in the request body describing exactly what it wants, and the server responds with only that data.

Key characteristics:

  • Single endpoint — everything goes through POST /graphql
  • Client-driven — the client defines the shape of the response
  • Strongly typed — every field has a declared type in the schema
  • Introspective — clients can query the API to discover its own structure

Core Concepts

1. Schema

The schema is the contract between client and server. It defines every type, every field, and every operation the API supports. It is written in SDL (Schema Definition Language):

typeUser{id:ID!name:String!email:String!posts:[Post!]!}typePost{id:ID!title:String!body:String!author:User!}typeQuery{user(id:ID!):Userposts:[Post!]!}typeMutation{createUser(name:String!,email:String!):User!deleteUser(id:ID!):Boolean!}

The ! means the field is non-nullable — it will never return null.


2. Query

A Query is a read operation — the equivalent of GET in REST. The client specifies exactly which fields it wants:

query{user(id:"123"){nameemailposts{title}}}

Response:

{"data":{"user":{"name":"Anne","email":"anne@example.com","posts":[{"title":"My first post"},{"title":"Learning GraphQL"}]}}}

One request. Nested data. Only the fields that were asked for.


3. Mutation

A Mutation is a write operation — the equivalent of POST, PUT, or DELETE in REST:

mutation{createUser(name:"Anne",email:"anne@example.com"){idname}}

Response:

{"data":{"createUser":{"id":"456","name":"Anne"}}}

4. Subscription

A Subscription is a real-time operation. The client subscribes to an event, and the server pushes data whenever that event occurs — powered by WebSockets under the hood:

subscription{newMessage(roomId:"general"){contentsender{name}}}

The server pushes a new message to every subscribed client as soon as it is sent.


GraphQL vs REST

Feature REST GraphQL
Endpoints Multiple (/users, /posts, ...) Single (/graphql)
Data shape Fixed by the server Defined by the client
Over-fetching Common Eliminated
Under-fetching Common Eliminated
Versioning /v1/, /v2/ Schema evolution via deprecation
Type system None (unless OpenAPI) Built-in, strongly typed
Real-time Requires polling or SSE Native via Subscriptions
Learning curve Low Medium
Best for Simple CRUD APIs Complex, nested, or client-diverse data

Using GraphQL in Go

GraphQL over HTTP is just a POST request with a JSON body — no special library needed for the client side.

Sending a GraphQL Query

package main

import (
 "bytes"
 "encoding/json"
 "fmt"
 "io"
 "net/http"
)

type GraphQLRequest struct {
 Query string `json:"query"`
 Variables map[string]any `json:"variables,omitempty"`
}

type GraphQLResponse struct {
 Data map[string]any `json:"data"`
 Errors []struct {
 Message string `json:"message"`
 } `json:"errors,omitempty"`
}

func main() {
 url := "https://api.example.com/graphql"

 // 1. Build the request body
 gqlReq := GraphQLRequest{
 Query: `
 query GetUser($id: ID!) {
 user(id: $id) {
 name
 email
 posts {
 title
 }
 }
 }
 `,
 Variables: map[string]any{
 "id": "123",
 },
 }

 body, err := json.Marshal(gqlReq)
 if err != nil {
 panic(err)
 }

 // 2. Send the POST request
 resp, err := http.Post(url, "application/json", bytes.NewBuffer(body))
 if err != nil {
 panic(err)
 }
 defer resp.Body.Close()

 // 3. Read and decode the response
 raw, _ := io.ReadAll(resp.Body)

 var gqlResp GraphQLResponse
 if err := json.Unmarshal(raw, &gqlResp); err != nil {
 panic(err)
 }

 // 4. Check for GraphQL-level errors
 if len(gqlResp.Errors) > 0 {
 fmt.Printf("GraphQL Error: %s\n", gqlResp.Errors[0].Message)
 return
 }

 fmt.Printf("Response: %+v\n", gqlResp.Data)
}

Sending a Mutation

gqlReq := GraphQLRequest{
 Query: `
 mutation CreateUser($name: String!, $email: String!) {
 createUser(name: $name, email: $email) {
 id
 name
 }
 }
 `,
 Variables: map[string]any{
 "name": "Anne",
 "email": "anne@example.com",
 },
}

Building a GraphQL server in Go? The most popular library is gqlgen — it generates type-safe Go code directly from your schema. Install it with go get github.com/99designs/gqlgen.


Summary

Concept What It Is
GraphQL A query language and runtime for APIs
Schema The typed contract defining all available data and operations
Query A read operation — asks for specific fields
Mutation A write operation — creates, updates, or deletes data
Subscription A real-time operation — server pushes events to the client
Single endpoint All operations go through one URL (POST /graphql)

Further Reading & Watch


GraphQL solves the data-fetching problem beautifully — the client asks, the server delivers. But notice something: everything above is still request/response. The client asks, waits, gets an answer. Even subscriptions require a special setup.

What if you needed a persistent, two-way channel where the server can push data to the client at any time, without the client asking first? That is where REST and GraphQL both step aside and let WebSockets take over. Stay tuned.