Version 2 of the Go SDK supports SurrealDB 4.0. It changes the module path, the supported server versions, and how the SDK sends some Go values to the server. This guide lists each change that can break a project written for version 1, with the 1.x code and the 2.x code that replaces it. The sections are in order of how much code each change usually affects, so work through them from the top.
Version 1 cannot write a time.Time to SurrealDB 4.0. It sends a bare time.Time as text, which SurrealDB 4.0 refuses with CBOR tag 0 (a datetime as text) is not accepted: send tag 12 [seconds, nanos]. Version 2 works with SurrealDB 3.3.0 and later. If the server is older than 3.3, upgrade it to 3.3 or later first. Then move to version 2 while the server runs 3.3 or a later 3.x release. After that, upgrade the server to 4.0.
What changed
The module path is
github.com/surrealdb/surrealdb.go/v2, so every import changes.The SDK supports SurrealDB 3.3.0 and later, before 5.0.0. Version 1 supported 2.1.0 and later.
The SDK sends a zero
time.TimeasNONEand atime.Durationas aduration, and refuses aregexp.Regexp.On SurrealDB 4.0 the SDK uses cbor.2. Sized numbers keep their kind when the SDK sends them and when it receives them, and decoding into
anygives the exact Go type.The CRUD functions run SurrealQL through the
queryRPC method, so the text of some errors is different.surrealql.SinceVersionstampsends the versionstamp unchanged.
1. Install version 2 and update imports
Add the new module:
go get github.com/surrealdb/surrealdb.go/v2Then change every import of the SDK, including pkg/..., contrib/... and memory, to the /v2 path:
import (
surrealdb "github.com/surrealdb/surrealdb.go"
"github.com/surrealdb/surrealdb.go/pkg/models"
)import (
surrealdb "github.com/surrealdb/surrealdb.go/v2"
"github.com/surrealdb/surrealdb.go/v2/pkg/models"
)The package names do not change, so the code that uses them stays as it is. To rewrite the imports in every Go file of a module at once, run this command from the module root:
perl -pi -e 's#"github\.com/surrealdb/surrealdb\.go(?!/v2)#"github.com/surrealdb/surrealdb.go/v2#g' $(grep -rl --include='*.go' 'github.com/surrealdb/surrealdb.go' .)Then remove the version 1 requirement from go.mod:
go mod tidyVersion 2 needs Go 1.24 or later, as the later 1.x releases do.
2. Check the server version
Version 2 supports SurrealDB 3.3.0 and later versions before 5.0.0, pre-releases included. SurrealDB 4.0 is the recommended version. With a 3.x server, the kinds that 4.0 adds are not available, and error kinds are less precise.
The SDK does not check the version unless you ask it to. With WithVersionCheck(true), connecting to a 2.x, 3.0, 3.1 or 3.2 server now fails with an UnsupportedVersionError:
db, err := surrealdb.FromEndpointURLStringWithOptions(ctx, "ws://localhost:8000",
surrealdb.WithVersionCheck(true),
)SurrealDB server version "3.2.4+20260803.93ab219" is not supported by this SDK (supported: >= 3.3.0, < 5.0.0); to connect anyway, turn the check off with surrealdb.WithVersionCheck(false)surrealdb.MinimumServerVersion is now "3.3.0", and IsVersionSupported returns false for versions before it. Code that compares a version with MinimumServerVersion itself, for example in a health check, now refuses servers that version 1 accepted.
3. Check the Go values your code sends
Version 2 sends some standard library values as different SurrealDB kinds:
| Go value | 1.x sent | 2.x sends |
|---|---|---|
A zero time.Time | NULL | NONE |
A time.Time that is not zero | Its text, which SurrealDB 4.0 refuses | A datetime, with its nanoseconds |
time.Duration | An int of nanoseconds | A duration |
regexp.Regexp, *regexp.Regexp | An empty object {} | An encoding error. Use models.Regex. |
A uint64 above math.MaxInt64 | An integer that SurrealDB refuses | A decimal, or a u64 on SurrealDB 4.0 |
A models.CustomDurationString that is not a valid duration | A string | An encoding error |
The SDK converts these values wherever they are: in a struct field, a map, a slice, or a variable of Query.
Then check the schema for the fields that your code writes these values to:
A field of
TYPE datetime | nullrefuses a zerotime.Time, because the SDK now sends that value asNONE. The error isExpected `datetime | null` but found `NONE`. Define the field asoption<datetime>, or send anil*time.Timeto storeNULL.A field of
TYPE intthat stores atime.Durationrefuses the new values, withExpected `int` but found `1m`. A query that compares such a field with an integer also stops matching. Give the field a type that accepts aduration, such asint | duration. Integers that are already stored still decode into atime.Duration.Use a
models.Regexfor a regular expression. Amodels.Regexholds the pattern as text. SurrealDB compiles the pattern with the syntax of the Rustregexcrate, which is close to Go's but not the same.
pattern := regexp.MustCompile(`^[a-z]+$`)
db.Let(ctx, "pattern", pattern)pattern := models.Regex{Pattern: `^[a-z]+$`}
db.Let(ctx, "pattern", pattern)A models.Regex needs SurrealDB 4.0. Over plain CBOR, which earlier servers use, it fails to encode. See Value types for every kind.
4. Check values that you read into any
On WebSocket and HTTP, the SDK now offers cbor.2, the CBOR dialect of SurrealDB 4.0. The SDK uses cbor.2 when the server accepts it. Over cbor.2:
The SDK sends
int8,uint8,int16,uint16,int32,uint32andfloat32values as the sized numbersi8tou32andf32, andmodels.Float16asf16.A sized number decodes into
anyas the exact Go type, such asint8orfloat32. Version 1 gave a wideneduint64,int64orfloat64. The new kinds of SurrealDB 4.0 decode intoanyas theirmodelstypes, such asmodels.PlainDateandmodels.Regex.
Code that decodes into any or map[string]any and then asserts the type can stop matching. In this example, the program wrote the level field from a Go int32. Version 1 stored the value as an int, which read back as a uint64. Version 2 stores it as an i32, which reads back as an int32:
level := row["level"].(uint64)level := row["level"].(int32)If you decode into a struct field of a concrete type, such as Level int, the SDK converts every numeric kind. This works the same in both versions. It is the simpler fix when you know the shape of the data.
To keep plain CBOR, set DisableCBORv2 in the connection configuration. db.CBORVersion() reports which version a connection uses. A connection that uses the deprecated models.CborMarshaler and models.CborUnmarshaler stays on plain CBOR.
5. Allow for CRUD functions that run as queries
Select, Create, Update, Upsert, Merge, Patch, Delete, Insert, InsertRelation, Relate, Live and Kill now send a SurrealQL statement with the query RPC method. In version 1, each of these functions called its own RPC method, such as select or insert_relation. Results have the same shape, and a failure is still an *RPCError that unwraps to a *ServerError.
Two things can be different:
The text of an error message. Match on the error kind rather than on the message. Use
errors.Asor anIs*helper, such assurrealdb.IsNotFound.Server settings that limit the
querymethod now apply to these functions too.
6. Update SinceVersionstamp in the query builder
In the query builder, ShowChangesForTableQuery.SinceVersionstamp now sends the versionstamp as it is. Version 1 shifted it right by 16 bits first. Pass a versionstamp exactly as SHOW CHANGES returned it:
q := surrealql.ShowChangesForTable("reading").SinceVersionstamp(versionstamp).Limit(10)SINCE is inclusive. When you continue from the last change that you received, the server returns that change again.
7. Upgrading from a release before 1.8
Releases 1.6 to 1.8 added features that change how a client behaves by default. A project that moves to version 2 from an earlier 1.x release gets them too:
A WebSocket client reconnects by itself. When the connection drops, the client connects again and restores the namespace, database, variables, authentication, sessions and live queries. A request that you send during the reconnect waits until the reconnect finishes or its context ends. It does not fail at once. Pass
WithReconnect(false)for the earlier behaviour. See Reliable connections.Package
spectronis nowmemory. Import the Agent Memory client fromgithub.com/surrealdb/surrealdb.go/v2/memory.A live query channel closes when the server kills the query. A notification with the action
KILLEDends it.New methods and types for
Health,Refresh,Revoke,Reset, token renewal, selecting a range of records, the error kind helpers, and theSetandFilevalues.
Import path mapping
| 1.x import | 2.x import |
|---|---|
github.com/surrealdb/surrealdb.go | github.com/surrealdb/surrealdb.go/v2 |
github.com/surrealdb/surrealdb.go/pkg/models | github.com/surrealdb/surrealdb.go/v2/pkg/models |
github.com/surrealdb/surrealdb.go/pkg/connection | github.com/surrealdb/surrealdb.go/v2/pkg/connection |
github.com/surrealdb/surrealdb.go/pkg/constants | github.com/surrealdb/surrealdb.go/v2/pkg/constants |
github.com/surrealdb/surrealdb.go/surrealcbor | github.com/surrealdb/surrealdb.go/v2/surrealcbor |
github.com/surrealdb/surrealdb.go/contrib/rews | github.com/surrealdb/surrealdb.go/v2/contrib/rews |
github.com/surrealdb/surrealdb.go/contrib/surrealql | github.com/surrealdb/surrealdb.go/v2/contrib/surrealql |
github.com/surrealdb/surrealdb.go/memory | github.com/surrealdb/surrealdb.go/v2/memory |
New in version 2
The kinds that SurrealDB 4.0 adds:
models.PlainDate,PlainTime,TimestampandInterval,BigDecimalandFloat16, andRegex.QueryStream, to read the results of a query as the server sends them.RunandRunVersion,APIandGQL.PatchWithResult, to choose what a patch returns.After a reconnect, a live query restarts in the namespace and database where it started.
The context of each WebSocket request bounds the write of that request.
Migration checklist
Run
go get github.com/surrealdb/surrealdb.go/v2. Rewrite the imports. Then rungo mod tidy.Check that the server runs SurrealDB 3.3.0 or later. Upgrade the server to 4.0 after you upgrade the SDK.
Find the fields that store a zero
time.Timeor atime.Duration. Update their types in the schema.Replace every
regexp.Regexpthat your code sends to the server with amodels.Regex.Find type assertions on values that your code decodes into
any. Change them to allow for the sized Go types.Replace checks on error message text with checks on the error kind.
Pass versionstamps to
SinceVersionstampasSHOW CHANGESreturns them.Run your tests against SurrealDB 4.0.
Learn more
Go SDK 2.0.0 release notes for the full list of changes
Value types for how each SurrealDB kind maps onto Go
Connecting to SurrealDB for the connection options
Error handling for matching on error kinds