Skip to content

Command Comparison: go-redis → Glide

The SET command stores a key-value pair in Valkey, while GET retrieves the value associated with a key.

  • Both go-redis and Glide support these commands with similar syntax.

go-redis

err := rdb.Set(ctx, "key", "value", 0).Err()
if err != nil {
panic(err)
}
val, err := rdb.Get(ctx, "key").Result()
if err != nil {
panic(err)
}
fmt.Println("key", val) // "key value"
// With expiration
err = rdb.Set(ctx, "key", "value", time.Hour).Err()

Glide

_, err := client.Set(ctx, "key", "value")
if err != nil {
panic(err)
}
val, err := client.Get(ctx, "key")
if err != nil {
panic(err)
}
fmt.Println("key", val.Value()) // "key value"
// With expiration
import "github.com/valkey-io/valkey-glide/go/v2/options"
_, err = client.SetWithOptions(ctx, "key", "value", options.SetOptions{
Expiry: &options.Expiry{
Type: options.Seconds,
Count: 3600,
},
})

The SETEX command sets a key with an expiration time in seconds.

  • In go-redis, this is a dedicated function.
  • In Glide, expiration is handled using options within the Set() command.

go-redis

err := rdb.SetEx(ctx, "key", "value", time.Hour).Err()
if err != nil {
panic(err)
}

Glide

import "github.com/valkey-io/valkey-glide/go/v2/options"
_, err := client.SetWithOptions(ctx, "key", "value", options.SetOptions{
Expiry: &options.Expiry{
Type: options.Seconds,
Count: 3600,
},
})
if err != nil {
panic(err)
}

The SETNX command sets a key only if it does not already exist.

  • In go-redis, this is a dedicated function that returns true if the key was set, false if the key already exists.
  • In Glide, this is handled using options within the Set() command.

go-redis

result, err := rdb.SetNX(ctx, "key", "value", 0).Result()
if err != nil {
panic(err)
}
fmt.Println(result) // true if key was set, false if key exists

Glide

import "github.com/valkey-io/valkey-glide/go/v2/options"
result, err := client.SetWithOptions(ctx, "key", "value", options.SetOptions{
ConditionalSet: options.OnlyIfDoesNotExist,
})
if err != nil {
panic(err)
}
// Returns "OK" if key was set, nil if key exists
fmt.Println(result.Value()) // "OK" or empty if nil

The MSET command sets multiple key-value pairs in a single operation, while MGET retrieves values for multiple keys.

  • In go-redis, MSet() accepts a map or key-value pairs as arguments.
  • In Glide, MSet() accepts a map with key-value pairs.
  • For MGet(), go-redis accepts multiple keys as arguments, while Glide requires a slice of keys.

go-redis

// Multiple set
err := rdb.MSet(ctx, map[string]interface{}{
"key1": "value1",
"key2": "value2",
}).Err()
if err != nil {
panic(err)
}
// Multiple get
values, err := rdb.MGet(ctx, "key1", "key2").Result()
if err != nil {
panic(err)
}
fmt.Println(values) // [value1 value2]

Glide

// Multiple set
_, err := client.MSet(ctx, map[string]string{
"key1": "value1",
"key2": "value2",
})
if err != nil {
panic(err)
}
// Multiple get
values, err := client.MGet(ctx, []string{"key1", "key2"})
if err != nil {
panic(err)
}
// values is []models.Result[string]
for _, val := range values {
if val.IsNil() {
fmt.Println("nil")
} else {
fmt.Println(val.Value())
}
}

The INCR command increments the value of a key by 1, while DECR decrements it by 1.

  • Both go-redis and Glide support these commands in the same way.
  • The key must contain an integer value, otherwise an error will be returned.

go-redis

result, err := rdb.Incr(ctx, "counter").Result()
if err != nil {
panic(err)
}
fmt.Println(result) // 1
result, err = rdb.Decr(ctx, "counter").Result()
if err != nil {
panic(err)
}
fmt.Println(result) // 0

Glide

result, err := client.Incr(ctx, "counter")
if err != nil {
panic(err)
}
fmt.Println(result) // 1
result, err = client.Decr(ctx, "counter")
if err != nil {
panic(err)
}
fmt.Println(result) // 0

The INCRBY command increases the value of a key by a specified amount, while DECRBY decreases it by a specified amount.

  • Both go-redis and Glide support these commands in the same way.
  • The key must contain an integer value, otherwise an error will be returned.

go-redis

result, err := rdb.IncrBy(ctx, "counter", 5).Result()
if err != nil {
panic(err)
}
fmt.Println(result) // 5
result, err = rdb.DecrBy(ctx, "counter", 2).Result()
if err != nil {
panic(err)
}
fmt.Println(result) // 3

Glide

result, err := client.IncrBy(ctx, "counter", 5)
if err != nil {
panic(err)
}
fmt.Println(result) // 5
result, err = client.DecrBy(ctx, "counter", 2)
if err != nil {
panic(err)
}
fmt.Println(result) // 3

The APPEND command appends a value to the end of an existing string stored at a key.

  • Both go-redis and Glide support this command in the same way.
  • Returns the length of the string after the append operation.

go-redis

err := rdb.Set(ctx, "greeting", "Hello", 0).Err()
if err != nil {
panic(err)
}
length, err := rdb.Append(ctx, "greeting", " World").Result()
if err != nil {
panic(err)
}
fmt.Println(length) // 11
result, err := rdb.Get(ctx, "greeting").Result()
if err != nil {
panic(err)
}
fmt.Println(result) // "Hello World"

Glide

_, err := client.Set(ctx, "greeting", "Hello")
if err != nil {
panic(err)
}
length, err := client.Append(ctx, "greeting", " World")
if err != nil {
panic(err)
}
fmt.Println(length) // 11
result, err := client.Get(ctx, "greeting")
if err != nil {
panic(err)
}
fmt.Println(result.Value()) // "Hello World"

The GETRANGE command retrieves a substring from a string value stored at a key, while SETRANGE overwrites part of a string at a key starting at a specified offset.

  • Both go-redis and Glide support these commands in the same way.

go-redis

err := rdb.Set(ctx, "key", "Hello World", 0).Err()
if err != nil {
panic(err)
}
result, err := rdb.GetRange(ctx, "key", 0, 4).Result()
if err != nil {
panic(err)
}
fmt.Println(result) // "Hello"
length, err := rdb.SetRange(ctx, "key", 6, "Redis").Result()
if err != nil {
panic(err)
}
fmt.Println(length) // 11
updated, err := rdb.Get(ctx, "key").Result()
if err != nil {
panic(err)
}
fmt.Println(updated) // "Hello Redis"

Glide

_, err := client.Set(ctx, "key", "Hello World")
if err != nil {
panic(err)
}
result, err := client.GetRange(ctx, "key", 0, 4)
if err != nil {
panic(err)
}
fmt.Println(result) // "Hello"
length, err := client.SetRange(ctx, "key", 6, "Redis")
if err != nil {
panic(err)
}
fmt.Println(length) // 11
updated, err := client.Get(ctx, "key")
if err != nil {
panic(err)
}
fmt.Println(updated.Value()) // "Hello Redis"

The DEL command removes one or more keys from Valkey.

  • In go-redis, Del() accepts multiple keys as separate arguments.
  • In Glide, Del() requires a slice of keys.

go-redis

result, err := rdb.Del(ctx, "key1", "key2").Result()
if err != nil {
panic(err)
}
fmt.Println(result) // 2 (number of keys deleted)

Glide

result, err := client.Del(ctx, []string{"key1", "key2"})
if err != nil {
panic(err)
}
fmt.Println(result) // 2 (number of keys deleted)

The EXISTS command checks if one or more keys exist in Valkey.

  • In go-redis, Exists() accepts multiple keys as separate arguments and returns the number of keys that exist.
  • In Glide, Exists() requires a slice of keys and also returns the number of keys that exist.

go-redis

result, err := rdb.Exists(ctx, "existKey", "nonExistKey").Result()
if err != nil {
panic(err)
}
fmt.Println(result) // 1 (number of keys that exist)

Glide

result, err := client.Exists(ctx, []string{"existKey", "nonExistKey"})
if err != nil {
panic(err)
}
fmt.Println(result) // 1 (number of keys that exist)

The EXPIRE command sets a time-to-live (TTL) for a key, after which it will be automatically deleted. The TTL command returns the remaining time-to-live for a key.

  • Both go-redis and Glide support these commands with similar syntax.

go-redis

result, err := rdb.Expire(ctx, "key", 10*time.Second).Result()
if err != nil {
panic(err)
}
fmt.Println(result) // true (success)
ttl, err := rdb.TTL(ctx, "key").Result()
if err != nil {
panic(err)
}
fmt.Println(ttl) // 10s (seconds remaining)

Glide

result, err := client.Expire(ctx, "key", 10*time.Second)
if err != nil {
panic(err)
}
fmt.Println(result) // true (success)
ttl, err := client.TTL(ctx, "key")
if err != nil {
panic(err)
}
fmt.Println(ttl) // 10 (seconds remaining)

The KEYS command returns all keys matching a pattern, while SCAN iterates through keys in a more efficient way for production use.

  • KEYS is not recommended for production use as it blocks the server until completion.
  • SCAN is the preferred method for iterating through keys in production environments.
  • In Glide, the cursor returned by Scan() needs to be handled using the models.Cursor type.

go-redis

// KEYS (not recommended for production)
allKeys, err := rdb.Keys(ctx, "*").Result()
if err != nil {
panic(err)
}
// SCAN (recommended for production)
var cursor uint64
var keys []string
for {
var err error
keys, cursor, err = rdb.Scan(ctx, cursor, "*", 10).Result()
if err != nil {
panic(err)
}
if len(keys) > 0 {
fmt.Println("SCAN iteration:", keys)
}
if cursor == 0 {
break
}
}

Glide

import "github.com/valkey-io/valkey-glide/go/v2/models"
// KEYS (not recommended for production)
allKeys, err := client.Keys(ctx, "*")
if err != nil {
panic(err)
}
// SCAN (recommended for production)
cursor := models.NewCursor("0")
for {
result, err := client.Scan(ctx, cursor)
if err != nil {
panic(err)
}
keys := result.Data
if len(keys) > 0 {
fmt.Println("SCAN iteration:", keys)
}
cursor = result.Cursor
if cursor.IsFinished() {
break
}
}

The RENAME command renames a key, while RENAMENX renames a key only if the new key does not already exist.

  • Both go-redis and Glide support these commands with similar syntax.

go-redis

err := rdb.Set(ctx, "oldkey", "value", 0).Err()
if err != nil {
panic(err)
}
result, err := rdb.Rename(ctx, "oldkey", "newkey").Result()
if err != nil {
panic(err)
}
fmt.Println(result) // "OK"
err = rdb.Set(ctx, "key1", "value1", 0).Err()
if err != nil {
panic(err)
}
success, err := rdb.RenameNX(ctx, "key1", "key2").Result()
if err != nil {
panic(err)
}
fmt.Println(success) // true (success)

Glide

_, err := client.Set(ctx, "oldkey", "value")
if err != nil {
panic(err)
}
result, err := client.Rename(ctx, "oldkey", "newkey")
if err != nil {
panic(err)
}
fmt.Println(result) // "OK"
_, err = client.Set(ctx, "key1", "value1")
if err != nil {
panic(err)
}
success, err := client.RenameNX(ctx, "key1", "key2")
if err != nil {
panic(err)
}
fmt.Println(success) // true (success)

The HSET command sets field-value pairs in a hash stored at a key, while HGET retrieves the value of a specific field.

  • In go-redis, HSet() accepts field-value pairs as separate arguments or a map.
  • In Glide, HSet() accepts a map with field-value pairs.

go-redis

// Set multiple fields
result, err := rdb.HSet(ctx, "hash", "key1", "1", "key2", "2").Result()
if err != nil {
panic(err)
}
fmt.Println(result) // 2 (fields added)
// Get a single field
value, err := rdb.HGet(ctx, "hash", "key1").Result()
if err != nil {
panic(err)
}
fmt.Println(value) // "1"

Glide

// Set multiple fields
result, err := client.HSet(ctx, "hash", map[string]string{
"key1": "1",
"key2": "2",
})
if err != nil {
panic(err)
}
fmt.Println(result) // 2 (fields added)
// Get a single field
value, err := client.HGet(ctx, "hash", "key1")
if err != nil {
panic(err)
}
fmt.Println(value.Value()) // "1"

The HMSET command sets multiple field-value pairs in a hash, while HMGET retrieves values for multiple fields.

  • In go-redis, HMSet() accepts either field-value pairs as arguments or a map.
  • In Glide, there is no separate HMSet() method; instead, HSet() is used for setting multiple fields.
  • For HMGet(), go-redis accepts multiple fields as arguments, while Glide requires a slice of fields.

go-redis

// Set multiple fields
err := rdb.HMSet(ctx, "hash", map[string]interface{}{
"key1": "1",
"key2": "2",
}).Err()
if err != nil {
panic(err)
}
// Get multiple fields
values, err := rdb.HMGet(ctx, "hash", "key1", "key2").Result()
if err != nil {
panic(err)
}
fmt.Println(values) // ["1", "2"]

Glide

// Set multiple fields (same as HSet in Glide)
_, err := client.HSet(ctx, "hash", map[string]string{
"key1": "1",
"key2": "2",
})
if err != nil {
panic(err)
}
// Get multiple fields
values, err := client.HMGet(ctx, "hash", []string{"key1", "key2"})
if err != nil {
panic(err)
}
// values is []models.Result[string]
for _, val := range values {
if val.IsNil() {
fmt.Println("nil")
} else {
fmt.Println(val.Value())
}
}

The HGETALL command retrieves all field-value pairs from a hash.

  • Both go-redis and Glide support this command in the same way.
  • Returns a map with field names as keys and their values.

go-redis

err := rdb.HSet(ctx, "user", map[string]interface{}{
"name": "John",
"age": "30",
}).Err()
if err != nil {
panic(err)
}
user, err := rdb.HGetAll(ctx, "user").Result()
if err != nil {
panic(err)
}
fmt.Println(user) // map[name:John age:30]

Glide

_, err := client.HSet(ctx, "user", map[string]string{
"name": "John",
"age": "30",
})
if err != nil {
panic(err)
}
user, err := client.HGetAll(ctx, "user")
if err != nil {
panic(err)
}
fmt.Println(user) // map[name:John age:30]

The HDEL command removes one or more fields from a hash, while HEXISTS checks if a field exists in a hash.

  • In go-redis, HDel() accepts multiple fields as separate arguments.
  • In Glide, HDel() requires a slice of fields.

go-redis

result, err := rdb.HDel(ctx, "hash", "field1", "field2").Result()
if err != nil {
panic(err)
}
fmt.Println(result) // 2 (fields deleted)
exists, err := rdb.HExists(ctx, "hash", "field1").Result()
if err != nil {
panic(err)
}
fmt.Println(exists) // false

Glide

result, err := client.HDel(ctx, "hash", []string{"field1", "field2"})
if err != nil {
panic(err)
}
fmt.Println(result) // 2 (fields deleted)
exists, err := client.HExists(ctx, "hash", "field1")
if err != nil {
panic(err)
}
fmt.Println(exists) // false

The LPUSH command adds elements to the head of a list, while RPUSH adds elements to the tail.

  • In go-redis, these commands accept multiple elements as separate arguments.
  • In Glide, these commands require a slice of elements.

go-redis

result, err := rdb.LPush(ctx, "list", "element1", "element2").Result()
if err != nil {
panic(err)
}
fmt.Println(result) // 2 (list length)
result, err = rdb.RPush(ctx, "list", "element3", "element4").Result()
if err != nil {
panic(err)
}
fmt.Println(result) // 4 (list length)

Glide

result, err := client.LPush(ctx, "list", []string{"element1", "element2"})
if err != nil {
panic(err)
}
fmt.Println(result) // 2 (list length)
result, err = client.RPush(ctx, "list", []string{"element3", "element4"})
if err != nil {
panic(err)
}
fmt.Println(result) // 4 (list length)

The LPOP command removes and returns an element from the head of a list, while RPOP removes and returns an element from the tail.

  • Both go-redis and Glide support these commands with similar syntax.

go-redis

value, err := rdb.LPop(ctx, "list").Result()
if err != nil {
panic(err)
}
fmt.Println(value) // "element2"
value, err = rdb.RPop(ctx, "list").Result()
if err != nil {
panic(err)
}
fmt.Println(value) // "element4"

Glide

value, err := client.LPop(ctx, "list")
if err != nil {
panic(err)
}
fmt.Println(value.Value()) // "element2"
value, err = client.RPop(ctx, "list")
if err != nil {
panic(err)
}
fmt.Println(value.Value()) // "element4"

The LRANGE command returns a range of elements from a list.

  • Both go-redis and Glide support this command with similar syntax.

go-redis

values, err := rdb.LRange(ctx, "list", 0, -1).Result()
if err != nil {
panic(err)
}
fmt.Println(values) // ["element1", "element3"]

Glide

values, err := client.LRange(ctx, "list", 0, -1)
if err != nil {
panic(err)
}
fmt.Println(values) // ["element1", "element3"]

The SADD command adds members to a set, while SMEMBERS returns all members of a set.

  • In go-redis, SAdd() accepts multiple members as separate arguments.
  • In Glide, SAdd() requires a slice of members.

go-redis

result, err := rdb.SAdd(ctx, "set", "member1", "member2").Result()
if err != nil {
panic(err)
}
fmt.Println(result) // 2 (members added)
members, err := rdb.SMembers(ctx, "set").Result()
if err != nil {
panic(err)
}
fmt.Println(members) // ["member1", "member2"]

Glide

result, err := client.SAdd(ctx, "set", []string{"member1", "member2"})
if err != nil {
panic(err)
}
fmt.Println(result) // 2 (members added)
members, err := client.SMembers(ctx, "set")
if err != nil {
panic(err)
}
// Convert map[string]struct{} to slice for printing
var memberSlice []string
for member := range members {
memberSlice = append(memberSlice, member)
}
fmt.Println(memberSlice) // ["member1", "member2"]

The SREM command removes members from a set, while SISMEMBER checks if a member exists in a set.

  • In go-redis, SRem() accepts multiple members as separate arguments.
  • In Glide, SRem() requires a slice of members.

go-redis

result, err := rdb.SRem(ctx, "set", "member1").Result()
if err != nil {
panic(err)
}
fmt.Println(result) // 1 (members removed)
exists, err := rdb.SIsMember(ctx, "set", "member1").Result()
if err != nil {
panic(err)
}
fmt.Println(exists) // false

Glide

result, err := client.SRem(ctx, "set", []string{"member1"})
if err != nil {
panic(err)
}
fmt.Println(result) // 1 (members removed)
exists, err := client.SIsMember(ctx, "set", "member1")
if err != nil {
panic(err)
}
fmt.Println(exists) // false

The ZADD command adds members with scores to a sorted set, while ZRANGE returns a range of members.

  • In go-redis, ZAdd() accepts score-member pairs.
  • In Glide, ZAdd() accepts a map with member-score pairs.

go-redis

import "github.com/redis/go-redis/v9"
result, err := rdb.ZAdd(ctx, "zset", redis.Z{Score: 1, Member: "member1"}, redis.Z{Score: 2, Member: "member2"}).Result()
if err != nil {
panic(err)
}
fmt.Println(result) // 2 (members added)
members, err := rdb.ZRange(ctx, "zset", 0, -1).Result()
if err != nil {
panic(err)
}
fmt.Println(members) // ["member1", "member2"]

Glide

result, err := client.ZAdd(ctx, "zset", map[string]float64{
"member1": 1.0,
"member2": 2.0,
})
if err != nil {
panic(err)
}
fmt.Println(result) // 2 (members added)
import "github.com/valkey-io/valkey-glide/go/v2/options"
members, err := client.ZRange(ctx, "zset", options.RangeByIndex{Start: 0, End: -1})
if err != nil {
panic(err)
}
fmt.Println(members) // ["member1", "member2"]

The ZRANK command returns the rank of a member in a sorted set (lowest to highest), while ZREVRANK returns the rank from highest to lowest.

  • Both go-redis and Glide support these commands with similar syntax.

go-redis

rank, err := rdb.ZRank(ctx, "zset", "member1").Result()
if err != nil {
panic(err)
}
fmt.Println(rank) // 0
revRank, err := rdb.ZRevRank(ctx, "zset", "member1").Result()
if err != nil {
panic(err)
}
fmt.Println(revRank) // 1

Glide

rank, err := client.ZRank(ctx, "zset", "member1")
if err != nil {
panic(err)
}
fmt.Println(rank.Value()) // 0
revRank, err := client.ZRevRank(ctx, "zset", "member1")
if err != nil {
panic(err)
}
fmt.Println(revRank.Value()) // 1

The ZREM command removes members from a sorted set, while ZSCORE returns the score of a member.

  • In go-redis, ZRem() accepts multiple members as separate arguments.
  • In Glide, ZRem() requires a slice of members.

go-redis

result, err := rdb.ZRem(ctx, "zset", "member1").Result()
if err != nil {
panic(err)
}
fmt.Println(result) // 1 (members removed)
score, err := rdb.ZScore(ctx, "zset", "member2").Result()
if err != nil {
panic(err)
}
fmt.Println(score) // 2.0

Glide

result, err := client.ZRem(ctx, "zset", []string{"member1"})
if err != nil {
panic(err)
}
fmt.Println(result) // 1 (members removed)
score, err := client.ZScore(ctx, "zset", "member2")
if err != nil {
panic(err)
}
fmt.Println(score.Value()) // 2.0

Transactions allow you to execute multiple commands atomically.

  • In go-redis, transactions are handled using TxPipeline().
  • In Glide, transactions are handled using batch operations with Exec().

go-redis

pipe := rdb.TxPipeline()
pipe.Set(ctx, "key1", "value1", 0)
pipe.Set(ctx, "key2", "value2", 0)
pipe.Incr(ctx, "counter")
results, err := pipe.Exec(ctx)
if err != nil {
panic(err)
}
fmt.Println(len(results)) // 3 (commands executed)

Glide

import "github.com/valkey-io/valkey-glide/go/v2/pipeline"
batch := pipeline.NewStandaloneBatch()
batch.Set("key1", "value1")
batch.Set("key2", "value2")
batch.Incr("counter")
results, err := client.Exec(ctx, batch, false)
if err != nil {
panic(err)
}
fmt.Println(len(results)) // 3 (commands executed)

The EVAL command executes Lua scripts, while EVALSHA executes scripts by their SHA1 hash.

  • Both go-redis and Glide support Lua script execution.
  • In Glide, scripts are managed using the Script type and InvokeScript() method.

go-redis

script := `
local key = KEYS[1]
local value = ARGV[1]
redis.call('SET', key, value)
return redis.call('GET', key)
`
result, err := rdb.Eval(ctx, script, []string{"mykey"}, "myvalue").Result()
if err != nil {
panic(err)
}
fmt.Println(result) // "myvalue"

Glide

import "github.com/valkey-io/valkey-glide/go/v2/options"
scriptCode := `
local key = KEYS[1]
local value = ARGV[1]
redis.call('SET', key, value)
return redis.call('GET', key)
`
script := options.NewScript(scriptCode)
result, err := client.InvokeScriptWithOptions(ctx, script, options.ScriptOptions{
Keys: []string{"mykey"},
Args: []string{"myvalue"},
})
if err != nil {
panic(err)
}
fmt.Println(result) // "myvalue"

Both libraries support executing custom or arbitrary Valkey commands.

  • In go-redis, use Do() method.
  • In Glide, use CustomCommand() method.

go-redis

result, err := rdb.Do(ctx, "PING").Result()
if err != nil {
panic(err)
}
fmt.Println(result) // "PONG"
// Custom command with arguments
result, err = rdb.Do(ctx, "SET", "customkey", "customvalue").Result()
if err != nil {
panic(err)
}
fmt.Println(result) // "OK"

Glide

result, err := client.CustomCommand(ctx, []string{"PING"})
if err != nil {
panic(err)
}
fmt.Println(result) // "PONG"
// Custom command with arguments
result, err = client.CustomCommand(ctx, []string{"SET", "customkey", "customvalue"})
if err != nil {
panic(err)
}
fmt.Println(result) // "OK"

Authentication is typically handled during connection setup, but can also be done explicitly.

  • In go-redis, authentication is usually set in the client options or can be done with Auth().
  • In Glide, authentication is set in the client configuration during connection setup.

go-redis

// During connection setup
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Username: "user",
Password: "password",
})
// Or explicitly after connection
result, err := rdb.Auth(ctx, "password").Result()
if err != nil {
panic(err)
}
fmt.Println(result) // "OK"

Glide

// During connection setup (recommended)
client, err := glide.NewClient(&config.ClientConfiguration{
Addresses: []config.NodeAddress{
{Host: "localhost", Port: 6379},
},
Credentials: &config.ServerCredentials{
Username: "user",
Password: "password",
},
})
// Authentication is handled automatically during connection