{"componentChunkName":"component---src-templates-doc-tsx","path":"/learn/caching/","result":{"data":{"doc":{"frontmatter":{"title":"Caching","date":null,"permalink":"/learn/caching/","byline":null,"guestBio":null,"sublinks":null,"layout":"docs"},"id":"64807002-e363-5637-aafc-4af37aa77f71","rawMarkdownBody":"\n> Providing Object Identifiers allows clients to build rich caches\n\nIn an endpoint-based API, clients can use HTTP caching to easily avoid refetching resources, and for identifying when two resources are the same. The URL in these APIs is a **globally unique identifier** that the client can leverage to build a cache. In GraphQL, though, there's no URL-like primitive that provides this globally unique identifier for a given object. It's hence a best practice for the API to expose such an identifier for clients to use.\n\n## Globally Unique IDs\n\nOne possible pattern for this is reserving a field, like `id`, to be a globally unique identifier. The example schema used throughout these docs uses this approach:\n\n```graphql\n# { \"graphiql\": true }\n{\n  starship(id:\"3003\") {\n    id\n    name\n  }\n  droid(id:\"2001\") {\n    id\n    name\n    friends {\n      id\n      name\n    }\n  }\n}\n```\n\nThis is a powerful tool to hand to client developers. In the same way that the URLs of a resource-based API provided a globally unique key, the `id` field in this system provides a globally unique key.\n\nIf the backend uses something like UUIDs for identifiers, then exposing this globally unique ID may be very straightforward! If the backend doesn't have a globally unique ID for every object already, the GraphQL layer might have to construct this. Oftentimes, that's as simple as appending the name of the type to the ID and using that as the identifier; the server might then make that ID opaque by base64-encoding it. \n\nOptionally, this ID can then be used to work with the [Global Object Identification](/learn/global-object-identification)'s `node` pattern.\n\n## Compatibility with existing APIs\n\nOne concern with using the `id` field for this purpose is how a client using the GraphQL API would work with existing APIs. For example, if our existing API accepted a type-specific ID, but our GraphQL API uses globally unique IDs, then using both at once can be tricky.\n\nIn these cases, the GraphQL API can expose the previous API's IDs in a separate field. This gives us the best of both worlds:\n\n - GraphQL clients can continue to rely on a consistent mechanism for getting a globally unique ID.\n - Clients that need to work with our previous API can also fetch `previousApiId` from the object, and use that.\n\n## Alternatives\n\nWhile globally unique IDs have proven to be a powerful pattern in the past, they are not the only pattern that can be used, nor are they right for every situation. The really critical functionality that the client needs is the ability to derive a globally unique identifier for their caching. While having the server derive that ID simplifies the client, the client can also derive the identifier. Oftentimes, this would be as simple as combining the type of the object (queried with `__typename`) with some type-unique identifier.\n\nAdditionally, if replacing an existing API with a GraphQL API, it may be confusing if all of the fields in GraphQL are the same **except** `id`, which changed to be globally unique. This would be another reason why one might choose not to use `id` as the globally unique field.\n"},"nextDoc":null},"pageContext":{"permalink":"/learn/caching/","nextPermalink":null,"sideBarData":[{"name":"Learn","links":[{"fileAbsolutePath":"/opt/build/repo/src/content/learn/Introduction.md","parent":{"relativeDirectory":"learn","sourceInstanceName":"content"},"frontmatter":{"title":"Introduction to GraphQL","permalink":"/learn/","next":"/learn/queries/","category":"Learn","sublinks":null,"sidebarTitle":"Introduction","date":null},"id":"7106674b-2f21-5d84-b8c3-c89c7e2b5561"},{"fileAbsolutePath":"/opt/build/repo/src/content/learn/Learn-Queries.md","parent":{"relativeDirectory":"learn","sourceInstanceName":"content"},"frontmatter":{"title":"Queries and Mutations","permalink":"/learn/queries/","next":"/learn/schema/","category":"Learn","sublinks":"Fields,Arguments,Aliases,Fragments,Operation Name,Variables,Directives,Mutations,Inline Fragments","sidebarTitle":null,"date":null},"id":"d9731a25-3fbf-5586-ae79-95daca042058"},{"fileAbsolutePath":"/opt/build/repo/src/content/learn/Learn-Schema.md","parent":{"relativeDirectory":"learn","sourceInstanceName":"content"},"frontmatter":{"title":"Schemas and Types","permalink":"/learn/schema/","next":"/learn/validation/","category":"Learn","sublinks":"Type System,Type Language,Object Types and Fields,Arguments,The Query and Mutation Types,Scalar Types,Enumeration Types,Lists and Non-Null,Interfaces,Union Types,Input Types","sidebarTitle":null,"date":null},"id":"6a9e1e57-c0ff-542e-a525-c28f658ad0a7"},{"fileAbsolutePath":"/opt/build/repo/src/content/learn/Learn-Validation.md","parent":{"relativeDirectory":"learn","sourceInstanceName":"content"},"frontmatter":{"title":"Validation","permalink":"/learn/validation/","next":"/learn/execution/","category":"Learn","sublinks":null,"sidebarTitle":null,"date":null},"id":"f69c6420-bf79-56a6-b7af-09fbe09f7565"},{"fileAbsolutePath":"/opt/build/repo/src/content/learn/Learn-Execution.md","parent":{"relativeDirectory":"learn","sourceInstanceName":"content"},"frontmatter":{"title":"Execution","permalink":"/learn/execution/","next":"/learn/introspection/","category":"Learn","sublinks":null,"sidebarTitle":null,"date":null},"id":"4d6ab3f1-c361-55eb-9800-797f90c3d8f6"},{"fileAbsolutePath":"/opt/build/repo/src/content/learn/Learn-Introspection.md","parent":{"relativeDirectory":"learn","sourceInstanceName":"content"},"frontmatter":{"title":"Introspection","permalink":"/learn/introspection/","next":"/learn/best-practices/","category":"Learn","sublinks":null,"sidebarTitle":null,"date":null},"id":"2911ba27-f601-585a-a70f-3ad2cb78f9f3"}]},{"name":"Best Practices","links":[{"fileAbsolutePath":"/opt/build/repo/src/content/learn/BestPractice-Introduction.md","parent":{"relativeDirectory":"learn","sourceInstanceName":"content"},"frontmatter":{"title":"GraphQL Best Practices","permalink":"/learn/best-practices/","next":"/learn/thinking-in-graphs/","category":"Best Practices","sublinks":null,"sidebarTitle":"Introduction","date":null},"id":"2f5369f2-a0d4-5f71-972e-6569092db7a4"},{"fileAbsolutePath":"/opt/build/repo/src/content/learn/BestPractice-ThinkingInGraphs.md","parent":{"relativeDirectory":"learn","sourceInstanceName":"content"},"frontmatter":{"title":"Thinking in Graphs","permalink":"/learn/thinking-in-graphs/","next":"/learn/serving-over-http/","category":"Best Practices","sublinks":null,"sidebarTitle":null,"date":null},"id":"692af90e-5600-50bd-bdd7-9048bc299512"},{"fileAbsolutePath":"/opt/build/repo/src/content/learn/BestPractice-ServingOverHTTP.md","parent":{"relativeDirectory":"learn","sourceInstanceName":"content"},"frontmatter":{"title":"Serving over HTTP","permalink":"/learn/serving-over-http/","next":"/learn/authorization/","category":"Best Practices","sublinks":null,"sidebarTitle":null,"date":null},"id":"fbee8a12-2a83-51c2-b7f3-068438a89b9b"},{"fileAbsolutePath":"/opt/build/repo/src/content/learn/BestPractice-Authorization.md","parent":{"relativeDirectory":"learn","sourceInstanceName":"content"},"frontmatter":{"title":"Authorization","permalink":"/learn/authorization/","next":"/learn/pagination/","category":"Best Practices","sublinks":null,"sidebarTitle":null,"date":null},"id":"2439b6ee-f2a2-5bbe-97d2-0f185a0b4aa8"},{"fileAbsolutePath":"/opt/build/repo/src/content/learn/BestPractice-Pagination.md","parent":{"relativeDirectory":"learn","sourceInstanceName":"content"},"frontmatter":{"title":"Pagination","permalink":"/learn/pagination/","next":"/learn/global-object-identification/","category":"Best Practices","sublinks":null,"sidebarTitle":null,"date":null},"id":"5602cb49-7976-5673-8868-32155bd8b94e"},{"fileAbsolutePath":"/opt/build/repo/src/content/learn/BestPractice-NodeInterface.md","parent":{"relativeDirectory":"learn","sourceInstanceName":"content"},"frontmatter":{"title":"Global Object Identification","permalink":"/learn/global-object-identification/","next":"/learn/caching/","category":"Best Practices","sublinks":null,"sidebarTitle":null,"date":null},"id":"62587b8a-8864-5487-b7db-8aacf4d0e464"},{"fileAbsolutePath":"/opt/build/repo/src/content/learn/BestPractice-Caching.md","parent":{"relativeDirectory":"learn","sourceInstanceName":"content"},"frontmatter":{"title":"Caching","permalink":"/learn/caching/","next":null,"category":"Best Practices","sublinks":null,"sidebarTitle":null,"date":null},"id":"64807002-e363-5637-aafc-4af37aa77f71"}]}],"sourcePath":"src/content/learn/BestPractice-Caching.md"}},"staticQueryHashes":["1581580458"]}