GraphQL in Production · Advanced GraphQL

Files and Binary Data in GraphQL

Why multipart uploads are discouraged and what to do instead.

Create a free account to save this page, take notes and track your progress. Sign in

The GraphQL multipart request spec exists, but uploading files through GraphQL servers is discouraged: it complicates CSRF protection, buffering and gateways. The common pattern is: a mutation returns a pre-signed upload URL, the client uploads directly to object storage, then a second mutation attaches the uploaded file. Return files as URLs (signed, short-lived for private content), never base64 blobs in responses.

Upload options

Criterion Multipart via GraphQL Pre-signed URL flow Base64 in JSON
Server load High None Very high (+33% size)
CSRF exposure Needs extra care None None
Large files Poor Excellent Unusable
Gateway support Inconsistent Universal Universal
type Mutation {
  createUpload(input: CreateUploadInput!): CreateUploadPayload!   # returns signed URL + uploadId
  attachAvatar(input: AttachAvatarInput!): AttachAvatarPayload!   # uploadId → user.avatar
}
type CreateUploadPayload { uploadId: ID!  url: String!  fields: JSON  expiresAt: DateTime! }

Common pitfalls

  • Base64 file payloads.
  • Multipart endpoints without CSRF protection.
  • Long-lived public file URLs.

Key points

  • Signed URL + attach mutation
  • Files as URLs in responses
  • Avoid base64

Further reading: Apollo: File uploads guidance

Practice questions

Why is multipart upload support in GraphQL servers a CSRF concern?

Answer

Multipart/form-data is a 'simple' content type browsers can send cross-site without preflight, so cookie-authenticated endpoints accepting it need explicit CSRF protection.

How should a GraphQL API return a private file?

Answer

As a short-lived signed URL field, generated after authorization, rather than embedding file bytes.

Open in the app to mark lessons complete, take notes and track your progress.

Was this page helpful?