# Connecting to SurrealDB

The SurrealDB SDK for JavaScript enables simple and advanced querying of a remote or embedded database.

When creating a new connection to a SurrealDB instance, you can choose to connect to a local or remote endpoint, specify a namespace and database pair to use, authenticate with an existing token, authenticate using a pair of credentials, or use advanced custom logic to prepare the connection to the database.

First, you need to initialise a new instance of the Surreal class and connect it to a database endpoint using the `.connect()` method. Then you can specify the connection details such as the URL, namespace, and database.

## API references

<table>
	<thead>
		<tr>
			<th scope="col">Method</th>
			<th scope="col">Description</th>
		</tr>
	</thead>
	<tbody>
		<tr>
			<td scope="row" data-label="Method"><a href="/docs/reference/javascript/api/core/surreal.md#connect"> <code> db.connect(url, options) </code></a></td>
			<td scope="row" data-label="Description">Connects to a local or remote database endpoint</td>
		</tr>
        <tr>
            <td scope="row" data-label="Method"><a href="/docs/reference/javascript/api/core/surreal.md#close"> <code> db.close() </code></a></td>
            <td scope="row" data-label="Description">Closes the persistent connection to the database</td>
        </tr>
        <tr>
            <td scope="row" data-label="Method"><a href="/docs/reference/javascript/api/core/surreal.md#ready"> <code> db.ready </code></a></td>
			<td scope="row" data-label="Description">Waits for the connection to the database to succeed</td>
		</tr>
		<tr>
			<td scope="row" data-label="Method"><a href="/docs/reference/javascript/api/core/surreal-session.md#use"> <code> db.use(namespace, database)</code></a></td>
			<td scope="row" data-label="Description">Switch to a specific namespace and database</td>
		</tr>
	</tbody>
</table>

## Opening a connection

Before you can execute any queries, you need to open a connection to a SurrealDB instance. This is done using the `.connect()` method.
This method accepts a connection string and a set of options, including namespace, database, and authentication details.

### Connection string

The connection string represents a URI pointing to a SurrealDB instance. Supported connection protocols include:

- **WebSocket** (`ws://`) for long lived connections (e.g. backend or frontend applications)
- **HTTP** (`http://`) for short lived stateless connections (e.g. server-side rendering applications)
- **Embedded** protocols using the [WebAssembly engine](/docs/reference/javascript/engines/wasm.md) or [Node.js engine](/docs/reference/javascript/engines/node.md)

**Local endpoint**

```ts
// Over WebSocket
await db.connect('ws://127.0.0.1:8000');

// Over HTTP
await db.connect('http://127.0.0.1:8000');
```

**Remote endpoint**

```ts
// Over WebSocket
await db.connect('wss://cloud.surrealdb.com');

// Over HTTP
await db.connect('https://cloud.surrealdb.com');
```

**Embedded endpoint**

```ts
// In-memory database
await db.connect('mem://');

// IndexedDB database (browser)
await db.connect('indxdb://localhost:8000');

// File-system database (backend)
await db.connect('rocksdb://localhost:8000');
```

### Connection options

The optional connection options allow you to further configure the connection to the database, including namespace and database, reconnect logic, and authentication details.

#### Namespace and database

You can directly specify the [namespace](/docs/reference/query-language/statements/define/namespace.md) and [database](/docs/reference/query-language/statements/define/database.md) to use using the `namespace` and `database` options. If you do not specify these options, the default namespace and database will be used.
Once the connection is established, you can switch the active namespace and database with the `.use()` method.

#### Authentication details

When connecting as a [system user](/docs/learn/security/authentication/authentication.md#system-users) or [token](/docs/learn/security/authentication/authentication.md#token), you can directly pass your credentials to the `authentication` option.
While you can also use the dedicated `.signin()` method to authenticate, passing the authentication details to the `.connect()` method is the preferred way and allows for automatic reconnecting.

#### Reconnection behaviour

You can configure the reconnection behaviour using the `reconnect` option. The SDK features a built-in reconnection mechanism for WebSocket connections that automatically reconnects to the database if the connection is lost.
Additionally, you can configure the behaviour with exponential backoff and jitter to prevent overwhelming the database with reconnection attempts.

| Option                | Description                                              |
|-----------------------|----------------------------------------------------------|
| `enabled`             | Enable automatic reconnection                            |
| `attempts`            | Maximum reconnection attempts (`-1` for unlimited)       |
| `retryDelay`          | Initial delay before reconnecting (ms)                   |
| `retryDelayMax`       | Maximum delay between attempts (ms)                      |
| `retryDelayMultiplier`| Multiply delay after each failed attempt                 |
| `retryDelayJitter`    | Random offset percentage for delays                      |

#### Retrying on write conflict

Under concurrent write load, a query can fail with a read/write conflict when another transaction touched the same data. You can configure the SDK to replay the conflicting work automatically with exponential backoff, using the `retry` option. It shares the same shape as `reconnect`, and is off by default since retrying a non-atomic multi-statement query could apply some statements more than once.

```ts
await db.connect('ws://localhost:8000', {
    namespace: 'my_namespace',
    database: 'my_database',
    retry: { enabled: true, attempts: 5, retryDelay: 100 }
});
```

This sets the connection-wide default. It can be overridden per call with `.retry()` on a [`query()`](/docs/reference/javascript/concepts/executing-queries.md) or on [mutation methods](/docs/reference/javascript/concepts/executing-queries.md) like `.create()` and `.delete()` - including when called on a [transaction](/docs/reference/javascript/concepts/transactions.md), since it exposes the same query methods.

```ts
const [n] = await db
    .query<[number]>('UPDATE counter:c SET n += 1 RETURN n')
    .retry({ attempts: 3 })
    .collect();
```

### Waiting for a connection

You can wait for the connection to the database to succeed by awaiting the `.connect()` method. If the connection fails for any reason, the promise will reject.
If you want to await without opening a connection, you can make use of the `.ready()` method instead.

```ts
// Open a new connection and wait for it to succeed
await db.connect('ws://127.0.0.1:8000');

// Wait for the connection to succeed without opening a new connection
await db.ready();
```

### Effect of connection protocol on token & session duration

The connection protocol you choose affects how authentication tokens and sessions work

- **Websocket** connections open a single long-lived stateful connection where after the initial authentication, the session duration applies and if not specified, defaults to `NONE` meaning that the session never expires unless otherwise specified.
- **HTTP** connections are short-lived and stateless, requiring you to authenticate every request individually for which the token is used, creating a short lived session. Hence, the token duration which defaults to 1 hour applies.

You can extend the session duration of a token or a session by setting the `DURATION` clause when creating a new access method with the [`DEFINE ACCESS METHOD`](/docs/reference/query-language/statements/define/access.md) statement, or when defining a new user with the [`DEFINE USER`](/docs/reference/query-language/statements/define/user.md) statement.
Learn more about token and session duration in our [security best practices](/docs/learn/security/best-practices/security-best-practices.md#expiration) documentation.

## Selecting a namespace and database

While an initial namespace and database can be specified directly in the `.connect()` method, you can also switch to a specific namespace and database using the `.use()` method. This is particularly useful if you want to switch to a different setup after connecting.
You can also stay in the same namespace but switch to a different database.

```ts
await db.use({
	namespace: 'surrealdb',
	database: 'docs'
});
```

The SDK will emit a `using` event whenever the namespace or database is selected, including during the initial connection. This allows you to subscribe to namespace and database changes and react to them accordingly.

```ts
db.subscribe('using', ({ namespace, database }) => {
	console.log('Now using:', namespace, '/', database);
});
```

## Connection status

The status of the connection is available through the `.status` property. This allows you to check the current connection state and react to changes in the connection status. The possible values are:

- **disconnected** when the SDK is waiting for a connection to be opened
- **connecting** when a connection is currently being opened
- **connected** when the SDK is ready to communicate with the database and execute queries
- **reconnecting** when the connection dropped and the SDK is attempting to reconnect

Additionally the SDK exposes events for each of these states, allowing you to subscribe to connection state changes.

```ts
db.subscribe('connected', () => {
    console.log('Connected to the database');
});
```

## Closing a connection

The `.close()` method closes the persistent connection to the database. You should always call this method when you are done with the connection to free up resources.
Since this method is asynchronous, we highly recommend awaiting it to ensure that the connection is closed properly before proceeding.

```ts
await db.close();
```

## Testing for features

The SDK provides a built in feature testing mechanism to check if a specific feature is supported by the current connection. This is particularly useful to check if a feature is supported before using it, and to avoid errors or unexpected behaviour.

```ts
import { Features } from "surrealdb";

if (db.isFeatureSupported(Features.LiveQueries)) {
	// Execute a live query...
}
```

A complete [list of supported features](https://github.com/surrealdb/surrealdb.js/blob/main/packages/sdk/src/utils/features.ts) can be found in the source code.

## Learn more

- [Surreal API reference](/docs/reference/javascript/api/core/surreal.md) for the complete connection interface
- [ConnectOptions type reference](/docs/reference/javascript/api/types/#connectoptions) for all connection options
- [RetryOptions type reference](/docs/reference/javascript/api/types/#retryoptions) for retry-on-conflict configuration
- [Authentication](/docs/reference/javascript/concepts/authentication.md) for signing in and managing credentials
- [WebAssembly engine](/docs/reference/javascript/engines/wasm.md) for embedded browser databases
- [Node.js engine](/docs/reference/javascript/engines/node.md) for embedded server-side databases
- [Error handling](/docs/reference/javascript/concepts/error-handling.md) for connection and reconnection errors
- [Security best practices](/docs/learn/security/best-practices/security-best-practices.md) for production deployments
