In the tutorial on GraphQL authentication, the login
is a Mutation:
type Mutation {
post(url: String!, description: String!): Link!
signup(email: String!, password: String!, name: String!): AuthPayload
login(email: String!, password: String!): AuthPayload
}
Shouldn't the login be a Query since:
- The operation has no side-effects on the server.
- The goal is to query a token.
Am I missing something here ?
In the context of that example, login
should be a Query instead of a Mutation because its resolver has no side-effects, at least according to the spec. However, there's a couple of reasons you probably won't see that done in the wild:
If you're implementing authentication, you'll probably want to log your users' account activity, either by maintaining some data about login/logout events or at least including some sort of "last login" field on the account's record. Modifying that data would be a side effect.
A convention has evolved that treats any operations that result from user actions as Mutations, regardless of side-effects. You see this with react-apollo
, for example, where Query components fire the associated query on mount, while Mutation components simply expose a function that can be called to fire that query. If you're planning on using Apollo client-side, it's worthwhile to consider those sort of client features when designing your schema.
Mutations are ran sequentially, while queries are ran simultaneously. That means it'd be foreseeable to fire a login mutation and one or more other mutations after it within the same call, allowing you to utilize an authenticated context for the subsequent calls. The same could not be said for queries -- if login
is a query and you include other queries with it in the same operation, they will all begin resolving at the same time.
Outside of how they're executed (sequentially vs simultaneously), on the server-side, queries and mutations are effectively interchangeable. You could have queries with side-effects and mutations with no side effects. You probably should stick with conventions, but I think sometimes there's valid reasons where you may have to throw those conventions out the window.