A REST endpoint gives you exactly the response shape its author decided to return, and nothing else — the server controls the cost of every request because the server wrote the query. GraphQL inverts that relationship: the client writes the query, nesting fields as deep and as wide as the schema allows in a single round trip, and the server has to resolve whatever shape arrives. That flexibility is the entire reason teams adopt GraphQL, and it is also why a GraphQL endpoint fails in ways a REST endpoint structurally cannot — a single syntactically valid query can ask the resolver to walk a friends-of-friends-of-friends graph five levels deep, or request the same expensive field ten thousand times under ten thousand aliases, and the server will try, because nothing in the protocol stops it.
Two failure modes follow directly from that inversion. The first is resource exhaustion: a deeply nested or highly aliased query can force exponentially more resolver calls and database round trips than the request's byte size suggests, so a rate limiter counting requests per second sees one request and misses the fact that it costs as much as ten thousand. The second is information disclosure through introspection: GraphQL's own reflection capability, `__schema` and `__type`, lets any client ask the server to describe every type, field, and mutation it exposes, turning a production endpoint into a self-documenting map of the entire data model for anyone who queries it.
Neither failure mode is a flaw in GraphQL as a technology — both are the direct, foreseeable consequence of moving query composition from the server to the client, and this lesson is about the controls that put a bound back on what the client is allowed to compose.