Eden TanStack Query
Guides

Query Keys

Understanding query key structure and cache operations

Query Keys

Eden TanStack Query generates deterministic query keys from your route paths and input. These keys are used by TanStack Query for caching, deduplication, and invalidation.

Key Structure

Query keys follow this structure:

// queryKey() returns:
[['path', 'segments', 'method'], { input: { ... }, type: 'query' }]

// Examples:
eden.users.get.queryKey()
// => [['users', 'get'], { type: 'query' }]

eden.users.get.queryKey({ role: 'admin' })
// => [['users', 'get'], { input: { role: 'admin' }, type: 'query' }]

eden.users({ id: '1' }).get.queryKey()
// => [['users', 'get'], { input: { id: '1' }, type: 'query' }]

The type field differentiates regular queries from infinite queries:

eden.posts.get.infiniteQueryKey({ limit: 10 })
// => [['posts', 'get'], { input: { limit: 10 }, type: 'infinite' }]

Available Methods

queryKey()

Returns the query key for a specific route. Optionally accepts input for more specific targeting:

eden.users.get.queryKey()                              // all users queries
eden.users.get.queryKey({ role: 'admin' })  // specific input
eden.users({ id: '1' }).get.queryKey()                 // specific path params

queryFilter()

Returns a filter object (including queryKey) for use with TanStack Query's filter-based methods:

eden.users.get.queryFilter()
eden.users.get.queryFilter({ role: 'admin' })
eden.users.get.queryFilter(undefined, { exact: true, stale: true })

queryKey() generates keys with type: "query", which only matches regular queries. queryFilter() uses type: "any", which matches both regular and infinite queries — making it better suited for broad cache invalidation.

infiniteQueryKey()

Returns the query key for infinite queries:

eden.posts.get.infiniteQueryKey()
eden.posts.get.infiniteQueryKey({ limit: 10 })

infiniteQueryFilter()

Returns a filter object for infinite queries:

eden.posts.get.infiniteQueryFilter()
eden.posts.get.infiniteQueryFilter({ category: 'tech' })

mutationKey()

Returns the mutation key for a mutation route:

eden.users.post.mutationKey()
// => [['users', 'post']]

Cache Operations

invalidateQueries

Mark queries as stale and trigger a refetch:

const queryClient = useQueryClient()
const eden = useEden()

// Invalidate all users queries (partial matching)
queryClient.invalidateQueries({
  queryKey: eden.users.get.queryKey()
})

// Invalidate with queryFilter
queryClient.invalidateQueries(
  eden.users.get.queryFilter()
)

// Invalidate a specific user
queryClient.invalidateQueries({
  queryKey: eden.users({ id: '1' }).get.queryKey()
})

cancelQueries

Cancel in-flight queries (useful for optimistic updates):

await queryClient.cancelQueries({
  queryKey: eden.todos.get.queryKey()
})

getQueryData / setQueryData

Read and write the cache directly:

// Read cached data
const user = queryClient.getQueryData(
  eden.users({ id: '1' }).get.queryKey()
)

// Write to cache
queryClient.setQueryData(
  eden.users({ id: '1' }).get.queryKey(),
  { id: '1', name: 'Updated Name', email: 'updated@example.com' }
)

removeQueries

Remove queries from the cache entirely:

queryClient.removeQueries({
  queryKey: eden.users({ id: '1' }).get.queryKey()
})

Partial Matching

TanStack Query uses partial matching for query keys. A key without input matches all queries for that route:

// Invalidates ALL users queries, regardless of input
queryClient.invalidateQueries({
  queryKey: eden.users.get.queryKey()
})

// Only invalidates the specific query with role='admin'
queryClient.invalidateQueries({
  queryKey: eden.users.get.queryKey({ role: 'admin' })
})

This is useful for broad invalidation after mutations:

const createUser = useMutation({
  ...eden.users.post.mutationOptions(),
  onSuccess: () => {
    // Invalidates all users queries (list, filtered, by id, etc.)
    queryClient.invalidateQueries({
      queryKey: eden.users.get.queryKey()
    })
  },
})

For more details on how partial matching works, see the TanStack Query docs on query invalidation.

On this page