Skip to main content
Go to documentation:
⌘U
Weaviate Database

Develop AI applications using Weaviate's APIs and tools

Deploy

Deploy, configure, and maintain Weaviate Database

Query Agent

Run agentic search over your Weaviate Cloud collections

Weaviate Cloud

Manage and scale Weaviate in the cloud

Engram

Persistent memory for LLM agents and applications

Additional resources

Integrations
Weaviate Academy

Need help?

Weaviate LogoAsk AI Assistant⌘K
Support
Community Forum
Contributor guide

Migrating from the GraphQL API

What is changing and when​

The GraphQL API is deprecated as of October 26, 2026. Nothing changes on that day, and existing clusters keep working. Weaviate Cloud switches GraphQL off on December 1, 2026 for clusters that have not used it in the last 30 days, and on May 1, 2027 for all remaining clusters. Self-hosted Weaviate keeps GraphQL working until at least May 1, 2027. The first minor release after that date disables it by default, and you can switch it back on. It is removed in a later release, with no date set yet.

StageWeaviate CloudSelf-hosted
Deprecated, October 26, 2026Existing clusters keep working. New clusters are created with GraphQL disabled, as they already were before.Nothing changes. GraphQL keeps working until at least May 1, 2027.
Disabled by defaultAlready the case for new clusters.In the first minor release after May 1, 2027. You can switch GraphQL back on.
Switched off or removedSwitched off on December 1, 2026 for clusters that have not used GraphQL in the last 30 days. Switched off on all remaining clusters on May 1, 2027.Removed in a later release. No date is set yet.

Who this guide is for​

This guide is for developers who have working GraphQL Get and Aggregate queries and need to express the same searches through one of Weaviate's other query APIs. Typical reasons to be here:

  • The GraphQL API is deprecated. Code that still sends GraphQL queries stops working once GraphQL is disabled, so it needs to move before the dates above.
  • You are moving an application to a new Weaviate Cloud cluster, which is created with GraphQL disabled.
  • You are building in the browser or on an edge runtime, where a plain gRPC client cannot run.
  • You maintain an HTTP-only stack, such as a no-code or BI tool, or a language without an official Weaviate client such as PHP or Ruby.

Start at the top of this table and take the first row that describes your stack.

Your applicationRecommended pathWhy
Server or container appClient librariesFor Python, JavaScript/TypeScript on Node, Go, Java, and C#. Covers every Get and Aggregate construct and gives you typed results and generated request objects. The recommended path, and the right one for the large majority of applications.
Browser or edge runtimeTypeScript client for webFor the browser and runtimes such as Cloudflare Workers or Vercel. The same client API, carried over gRPC-Web so it works where plain gRPC cannot.
No client library availableREST Search APIFor a no-code or BI platform, or a language with no official client such as PHP or Ruby. Plain-HTTP JSON endpoints whose request bodies mirror your GraphQL queries closely.
Availability at a glance

The three paths are at three different maturity levels. Check the Status column before you commit to one.

PathStatusAvailability
Official client librariesGenerally availablePython, JavaScript/TypeScript, Go, Java, and C# are generally available.
@weaviate/web (browser and edge)Generally available3.15.0 and up. Requires Weaviate v1.38.3 or later. See the web client page.
REST Search APIPreviewEnabled on all Weaviate Cloud clusters. For open-source releases, enabled by default from v1.39.7. In v1.39.0 through v1.39.6 it needs EXPERIMENTAL_REST_SEARCH_ENABLED set to true. See REST Search API.

Do you need to migrate​

You need to migrate if any part of your application sends GraphQL to Weaviate. The two checks below tell you whether it does, and let you prove it before GraphQL is switched off.

Find your GraphQL usage​

GraphQL can reach Weaviate in three ways, and an older client can send it without you writing a single query.

Where GraphQL hides, and which client versions use it

Your code sends GraphQL queries if it does any of the following:

  • Calls the endpoint directly. It sends HTTP requests to /v1/graphql or /v1/graphql/batch, for example with curl or a generic HTTP library.
  • Uses a raw GraphQL helper. Some clients can pass a GraphQL query string straight to the server. These helpers always use GraphQL, whatever the client generation.
  • Uses an older client generation. Older clients, including the Go client v5, build their queries as GraphQL under the hood.

Check each client your code uses against this table:

ClientQueries over gRPC fromStill uses GraphQL when
Python weaviate-clientSearch: v4.4.0. Aggregate: v4.11.0, against Weaviate v1.29.0 or laterAggregate and len(collection) fall back to GraphQL on Weaviate older than v1.29.0. client.graphql_raw_query() always uses GraphQL.
TypeScript weaviate-clientSearch: v3.0.0. Aggregate: v3.4.0, against Weaviate v1.29.0 or laterAggregate falls back to GraphQL on Weaviate older than v1.29.0.
Java io.weaviate:client66.0.0Never.
C#1.0.0Never.
Go weaviate-go-client/v6v6.0.0Never.
Go weaviate-go-client/v5NeverAlways. client.GraphQL().Get(), .Aggregate(), .Explore() and .Raw() are its search API.

Test with GraphQL disabled​

A test instance with GraphQL switched off proves that your application no longer depends on it.

How to switch GraphQL off, and what a disabled endpoint returns

Run your application against an instance with GraphQL switched off before you rely on it. On a non-production self-hosted instance, set the DISABLE_GRAPHQL environment variable to true. It is also available as the disable_graphql runtime configuration key.

With GraphQL disabled, POST /v1/graphql and POST /v1/graphql/batch return HTTP 422 with this body:

{"error":[{"message":"graphql api is disabled"}]}

Authorization runs first, so a caller without read permission gets 403 instead. The Python client and the Go client v5 return an error that carries the same status code and message.

A new Weaviate Cloud cluster is already in this state, so you can also test against one.

The client libraries cover every Get and Aggregate construct shown on this page, so each one has a direct equivalent. They query over gRPC, and give you typed results and generated request objects.

GraphQL syntax mapping​

GraphQLClient conceptHow-to
Get { Collection { ... } }Fetch objects from a collectionSearch patterns and basics
nearTextNear-text searchSearch with text
nearObjectNear-object searchSearch with an existing object
nearVectorNear-vector search, passing your own query vectorSearch with a vector
nearImage and the other media operatorsMultimodal searchSearch with image
bm25Keyword search, including search operators and property boostsKeyword search
hybridHybrid search, including alpha, fusion type, and search vectorsHybrid search
whereFilters, built with the client's filter helpersFilters
limit, offsetlimit and offset argumentsPaginate with limit and offset
after (cursor)Cursor-based iteration over all objectsCursor with after
autocutauto_limit / autoLimitLimit result groups
sortSorting on object retrieval. Sorting is not combined with a search operator. See sorting considerationsSorting
_additional { ... }return_metadata / returnMetadata, returned as a metadata object on each resultRetrieve metadata values
_additional { vector }include_vector / returnVectorsRetrieve the object vector
groupByGrouped resultsGroup results
Aggregate { ... }The collection's aggregate API, including per-property statisticsAggregate data
_additional { generate { ... } }Retrieval augmented generation (single prompt and grouped task)Retrieval Augmented Generation (RAG)
Cross-reference selection (... on Target { ... })return_references / returnReferencesRetrieve cross-referenced properties
tenantA tenant-scoped collection handleMulti-tenancy
consistencyLevelA consistency-level-scoped collection handleReplication

TypeScript client for web​

If your application runs in a browser or on an edge runtime such as Cloudflare Workers or Vercel, a plain gRPC client cannot run there. @weaviate/web is a browser and edge build of the v3 TypeScript client that carries the query path over gRPC-Web, so you write the same client code you would on Node against a single HTTP(S) endpoint.

Install steps, the server version floor and the browser notes are on the web client page.

REST Search API​

Preview

As of Oct 26, 2026, the REST Search API is a preview feature.

The REST Search API is a set of plain-HTTP JSON endpoints intended for stacks that cannot run a client library. Request and response field names may still change, so this path is not recommended for production use yet. It is a deliberate subset of what GraphQL offers. Read Differences to check before you convert and Queries without a REST equivalent yet before you convert anything.

There are six available POST endpoints:

EndpointGraphQL equivalent
POST /v1/search/{collection}/near-textGet with nearText
POST /v1/search/{collection}/bm25Get with bm25
POST /v1/search/{collection}/hybridGet with hybrid
POST /v1/search/{collection}/near-objectGet with nearObject
POST /v1/search/{collection}/near-vectorGet with nearVector
POST /v1/aggregate/{collection}Aggregate

The near-vector endpoint is available from v1.39.8. It takes your own query vector, so it also works on collections without a vectorizer.

An example request​

The GraphQL query you are converting from is documented in the GraphQL reference. Its REST equivalent looks like this:

REST Search API: POST /v1/search/Movie/near-text

{
"query": ["space opera"],
"limit": 5,
"where": {
"operator": "And",
"operands": [
{ "path": ["year"], "operator": "GreaterThanEqual", "valueInt": 1980 },
{ "path": ["category"], "operator": "Equal", "valueText": "scifi" }
]
},
"returnProperties": ["title", "year"],
"returnMetadata": ["distance"]
}

The where value is the exact same JSON you pass in GraphQL. It uses the same 15 operators, the same value fields, and the same cross-reference paths, parsed by the same code. There is no new filter language to learn.

The response is a flat envelope rather than the GraphQL data.Get.<Collection> nesting:

{
"results": [
{
"id": "00000000-0000-0000-0000-000000000000",
"properties": { "title": "Dune", "year": 2021 },
"metadata": { "distance": 0.12 }
}
],
"tookMs": 8
}

Differences to check before you convert​

These are the conversions most likely to cost you time. Some return a perfectly successful response carrying a different answer from the one GraphQL gave. Others change the way a failure reaches your code. The silent ones are the dangerous ones. Read this list before the feature gaps below.

What changes, and what to do about it
DifferenceWhat happensWhat to do
Default limitGraphQL Get falls back to QUERY_DEFAULTS_LIMIT_GRAPHQL (100 by default). The REST endpoints fall back to QUERY_DEFAULTS_LIMIT (10 by default) and never reach the GraphQL value. A query you convert without an explicit limit silently returns far fewer rows.Always set limit explicitly. This is the single most common silent difference.
Unknown body fields are ignoredThe endpoints accept and discard fields they do not recognize, for platform parity with the rest of the REST API. A typo, or a field borrowed from GraphQL, produces a successful response that ignored your intent.Check every field name against the tables on this page.
bm25.searchOperatorThere is no REST field for the keyword search operator (And, Or, AndCross) or minimumOrTokensMatch. Supplying one is ignored, so the search runs with the default operator.Use a client library if your results depend on the search operator.
Get's group argumentThe vector-grouping group argument has no REST field and raises no error. Results come back ungrouped.Use a client library for grouped results.
A body field named generateSilently ignored, and the response contains no generated text. The reserved singlePrompt and groupedTask fields do return 422.See Queries without a REST equivalent yet.
certainty on a bm25 searchAccepted in returnMetadata, but certainty cannot be computed for a keyword search, so the field is simply absent from the response.Request score instead for keyword searches.
int64 precisionIntegers travel as JSON numbers and are handled as float64, so values beyond 2^53 lose precision.For large integers, use a client library, or store the value as text.
_additional is renamedRetrieval metadata arrives under a metadata key, not _additional. Properties and cross-references are also split into their own properties and references objects rather than sitting flat on the result, and the object id is a top-level envelope field.Update your response parsing. Note id is not a valid returnMetadata entry. Supplying it returns 422.
Error signallingGraphQL returns HTTP 200 with an errors[] array. The REST endpoints use real HTTP status codes (400, 401, 403, 404, 413, 422, 429, 500, 503) with a body of the form {"error":[{"message":"..."}]}.Check the status code, not just the body. Client code that only inspected errors[] will treat failures as successes.
Embedding-provider failuresWhen the vectorizer module fails, the response is 500, never 502, with a deliberately short message. The provider's own response goes to the server log, because it can quote credentials.Read the server log for provider errors. Do not parse the client-facing body.
The same validation, surfaced differentlyBoth APIs reject a malformed where filter with the same underlying message. That covers And/Or with no operands, a Not with more than one, a non-RFC3339 valueDate, a ContainsAny/ContainsAll/ContainsNone without an array value, and IsNull without indexNullState. GraphQL returns the error inside errors[] under HTTP 200. Here it arrives as a status code. Only the missing-operands case is caught at the API layer and returns 400. The other four are rejected deeper in the engine and return 500.Do not treat these 500s as transient server trouble: a retry or alerting rule keyed on 5xx will retry forever and page someone. Read the message before retrying.
fusionType values differGraphQL's rankedFusion and relativeScoreFusion are ranked and relativeScore here. A copied GraphQL value returns 422.Translate the value. See the cheat sheet below.

Queries without a REST equivalent yet​

These capabilities are not part of the preview. They fail in two very different ways, so check the status column before you port anything: some are reserved and return 422 or 400, which shows the gap in your logs. Others are simply not recognized, and the request returns 200 with the capability having had no effect at all. The silent ones are the ones to watch. If you need one of these, please open a GitHub issue.

What is missing, and what each returns
GraphQL capabilityREST statusPath
hybrid.vector, supplying the vector leg of a hybrid searchThe hybrid route exists but has no vector field, so the value is silently ignored (200) and the search runs against a server-computed vector instead of yours.Client libraries or the web client.
Aggregate property statistics such as sum, mean, median, mode, minimum, maximum, topOccurrences, totalTrue, and the restAggregate is count-only. A property:statistic entry in returnMetrics returns 422.Client libraries
Aggregate over a search, over and objectLimitReserved, returns 422.Client libraries
RAG, generate(singleResult:) and generate(groupedResult:)singlePrompt and groupedTask are reserved and return 422.Client libraries
Multiple target vectors, targetVectors and targetstargetVector takes a single string. On near-text, near-object, and hybrid an array returns 400. On bm25 there is no targetVector field at all, so any value, string or array, is silently ignored (200) through the unknown-field path. Multi-target weighting is not available.Client libraries
Media search, nearImage, nearAudio, nearVideo, nearDepth, nearThermal, nearImuNo routes.Client libraries
groupBy in GetReserved, but the status depends on the shape you send. The GraphQL-shaped object ({path, groups, objectsPerGroup}) is the form you are most likely to port, and it returns 400, because the reserved field is typed as a string. A bare string returns 422 "groupBy is not yet supported".Client libraries
rerankReserved, returns 422.Client libraries
sort and the after cursorNot fields on the search endpoints, so both are silently ignored (200, with the result set unchanged and unsorted). Sorting is not combined with search operators, as noted in sorting considerations, and both remain available on GET /v1/objects.Client libraries, or GET /v1/objects
nearText concept steering, moveTo, moveAwayFrom and autocorrectNot fields on the near-text route, so all three are silently ignored (200, with the result set unchanged and unsteered).Client libraries
Vectors in the response, _additional { vector }Vectors are never returned by these endpoints.Client libraries, or GET /v1/objects

GraphQL to REST cheat sheet​

Body fields are camelCase. Field names not listed here are not recognized, and unrecognized fields are ignored rather than rejected.

GraphQL to REST field map
GraphQLREST request body
nearText: { concepts: ["x", "y"] }POST /v1/search/{c}/near-text with "query": ["x", "y"]. Always an array, even for one concept
nearText: { certainty: 0.7 } or { distance: 0.3 }"certainty": 0.7 or "distance": 0.3. One or the other, not both
bm25: { query: "x", properties: ["title^2"] }POST /v1/search/{c}/bm25 with "query": "x", "queryProperties": ["title^2"]
hybrid: { query: "x", alpha: 0.5 }POST /v1/search/{c}/hybrid with "query": "x", "alpha": 0.5
hybrid: { fusionType: rankedFusion }"fusionType": "ranked"
hybrid: { fusionType: relativeScoreFusion }"fusionType": "relativeScore"
hybrid: { maxVectorDistance: 0.4 }"maxVectorDistance": 0.4. Requires alpha greater than 0, otherwise 400
nearObject: { id: "<uuid>" }POST /v1/search/{c}/near-object with "id": "<uuid>". Required, and must be a well-formed UUID
nearVector: { vector: [0.1, 0.2] }POST /v1/search/{c}/near-vector with "vector": [0.1, 0.2]. Required. Accepts certainty or distance like near-text
targetVectors: ["title_vector"]"targetVector": "title_vector". A single string
where: { ...WhereFilter... }"where": { ...the same JSON... }
limit: 5, offset: 10"limit": 5, "offset": 10
autocut: 1"autoLimit": 1
A property selection such as title year"returnProperties": ["title", "year"]. Omit the field for all non-reference properties, or pass [] for none
hasAuthor { ... on Author { name } }"returnReferences": [{ "linkOn": "hasAuthor", "targetCollection": "Author", "returnProperties": ["name"] }]. Dotted paths in returnProperties return 400
_additional { distance score explainScore }"returnMetadata": ["distance", "score", "explainScore"]. The response key is metadata
_additional { creationTimeUnix lastUpdateTimeUnix }"returnMetadata": ["creationTime", "lastUpdateTime"]
_additional { id }Nothing to request. id is always returned in the envelope. Passing "id" in returnMetadata returns 422
tenant: "tenantA""tenant": "tenantA"
consistencyLevel: ONE"consistencyLevel": "ONE". Uppercase only, "one" returns 422
Aggregate { C(groupBy: ["category"]) { meta { count } } }POST /v1/aggregate/{c} with "groupBy": "category", "returnMetrics": ["count"]. Use a bare property name, not a path. A dotted value returns 422
Aggregate { C { meta { count } } }POST /v1/aggregate/{c} with an empty body, or "returnMetrics": ["count"]

One more request limit worth knowing: limit, offset, and their sum are each capped by QUERY_MAXIMUM_RESULTS, and exceeding any of them returns 400. From v1.39.7, a request body larger than 4 MiB returns 413.

GraphQL features without an equivalent​

These GraphQL features have no equivalent in the gRPC API, the client libraries or the REST Search API today:

  • Explore
  • ask, from the qna modules
  • Summarization, from the sum-transformers module
  • Named entity recognition, from the ner-transformers module
  • spellCheck
  • The _additional properties featureProjection, semanticPath, interpretation and classification

If one of these is essential to your application, tell us through the channels under Questions and feedback. Within reason, we will add what is missing.

Further resources​

Questions and feedback​

All three paths are actively being developed, and feedback on this guide, especially a query you could not convert, directly shapes what gets built next.

We are helping with the migration through the support portal and support@weaviate.io. If a query has no equivalent in the paths above, tell us. We will work with you to find a solution, for example by adding additional parameters on the REST Search API.