Skip to Content
API ReferenceInstantDB

The InstantDB class is the main entry point for interacting with your InstantDB database. It provides methods for initialization, queries, transactions, authentication, and real-time synchronization.

Initialization

InstantDB.init()

Initialize a new InstantDB instance.

static Future<InstantDB> init({ required String appId, InstantConfig config = const InstantConfig(), })

Parameters:

  • appId (String): Your InstantDB application ID
  • config (InstantConfig, optional): Configuration options

Returns: Future<InstantDB> - The initialized database instance

Example:

final db = await InstantDB.init( appId: 'your-app-id', config: const InstantConfig( syncEnabled: true, verboseLogging: false, ), );

InstantConfig

Configuration options for InstantDB initialization.

class InstantConfig { const InstantConfig({ this.persistenceDir, this.syncEnabled = true, this.baseUrl = 'https://api.instantdb.com', this.maxCacheSize = 50 * 1024 * 1024, // 50MB this.reconnectDelay = const Duration(seconds: 1), this.verboseLogging = false, }); final String? persistenceDir; final bool syncEnabled; final String baseUrl; final int maxCacheSize; final Duration reconnectDelay; final bool verboseLogging; }

Properties:

  • persistenceDir (String?): Custom directory for SQLite database storage
  • syncEnabled (bool): Enable real-time synchronization (default: true)
  • baseUrl (String): Custom API endpoint URL (default: https://api.instantdb.com)
  • maxCacheSize (int): Maximum size of the local database cache in bytes (default: 50MB)
  • reconnectDelay (Duration): Delay between reconnection attempts (default: 1 second)
  • verboseLogging (bool): Enable detailed debug logging (default: false)

Core Properties

isReady

A reactive signal indicating if the database is initialized and ready for use.

ReadonlySignal<bool> get isReady

Example:

if (db.isReady.value) { print('Database is ready'); }

isOnline

A reactive signal indicating if the database is currently connected to the sync server.

ReadonlySignal<bool> get isOnline

Example:

Watch((context) { final online = db.isOnline.value; return Text(online ? 'Connected' : 'Disconnected'); });

appId

Get the application ID for this database instance.

String get appId

Returns: String - The application ID

Example:

print('Database app ID: ${db.appId}');

auth

Access the authentication manager.

AuthManager get auth

Returns: AuthManager - The authentication manager instance

Example:

final currentUser = db.auth.currentUser.value; if (currentUser != null) { print('User: ${currentUser.email}'); }

presence

Access the presence manager for real-time collaboration.

PresenceManager get presence

Returns: PresenceManager - The presence manager instance

Example:

final room = db.presence.joinRoom('chat-room'); await room.setPresence({'status': 'online'});

syncEngine

Access the internal synchronization engine. Note that most synchronization logic is handled automatically through db.query and db.transact.

SyncEngine get syncEngine

Returns: SyncEngine - The sync engine instance

Query Methods

query()

Create a reactive query that updates automatically when data changes. This is the preferred method for getting data.

Signal<QueryResult> query(Map<String, dynamic> query, {bool syncedOnly = false})

Parameters:

  • query (Map<String, dynamic>): The InstaQL query object
  • syncedOnly (bool, optional): If true, only returns entities that sync to cloud (excludes local-only entities)

Returns: Signal<QueryResult> - A reactive signal containing query results

Example:

final todosSignal = db.query({ 'todos': { 'where': {'completed': false}, 'orderBy': {'createdAt': 'desc'}, 'limit': 20, }, });

subscribeQuery()

Alias for query(), kept for API compatibility.

Signal<QueryResult> subscribeQuery(Map<String, dynamic> query)

Example:

final todosSignal = db.subscribeQuery({ 'todos': { 'where': {'completed': false}, 'orderBy': {'createdAt': 'desc'}, 'limit': 20, }, }); // Use in reactive widgets Watch((context) { final result = todosSignal.value; final todos = result.data?['todos'] ?? []; return TodoList(todos: todos); });

queryOnce()

Execute a one-time query without creating a subscription.

Future<QueryResult> queryOnce(Map<String, dynamic> query, {bool syncedOnly = false})

Parameters:

  • query (Map<String, dynamic>): The InstaQL query object
  • syncedOnly (bool, optional): If true, only returns entities that sync to cloud

Returns: Future<QueryResult> - The query result

Example:

final result = await db.queryOnce({ 'users': { 'where': {'role': 'admin'}, 'limit': 5, }, }); final adminUsers = result.data?['users'] ?? []; print('Found ${adminUsers.length} admin users');

Transaction Methods

transact()

Execute a transaction with a list of operations or transaction chunk.

Future<TransactionResult> transact(dynamic transaction)

Parameters:

  • transaction (List<Operation> or TransactionChunk): The operations to execute

Returns: Future<TransactionResult> - The transaction result

Example:

// With list of operations await db.transact([ ...db.create('todos', { 'id': db.id(), 'text': 'Learn InstantDB', 'completed': false, }), ]); // With transaction chunk (new tx API) await db.transact( db.tx['todos'][todoId].update({'completed': true}) );

transactChunk() (Deprecated)

Execute a transaction chunk. Use transact() instead.

@Deprecated('Use transact() instead') Future<TransactionResult> transactChunk(TransactionChunk chunk)

create()

Create a new entity operation.

List<Operation> create(String entityType, Map<String, dynamic> data)

Parameters:

  • entityType (String): The type of entity to create
  • data (Map<String, dynamic>): The entity data

Returns: List<Operation> - List containing the create operation

Example:

final operations = db.create('posts', { 'id': db.id(), 'title': 'Hello World', 'content': 'This is my first post', 'authorId': userId, 'createdAt': DateTime.now().millisecondsSinceEpoch, }); await db.transact(operations);

update()

Create an update entity operation.

Operation update(String entityId, Map<String, dynamic> data)

Parameters:

  • entityId (String): The ID of the entity to update
  • data (Map<String, dynamic>): The data to update

Returns: Operation - The update operation

Example:

await db.transact([ db.update(postId, { 'title': 'Updated Title', 'updatedAt': DateTime.now().millisecondsSinceEpoch, }), ]);

delete()

Create a delete entity operation.

Operation delete(String entityId)

Parameters:

  • entityId (String): The ID of the entity to delete

Returns: Operation - The delete operation

Example:

await db.transact([ db.delete(postId), ]);

merge()

Create a deep merge operation.

Operation merge(String entityId, Map<String, dynamic> data)

Parameters:

  • entityId (String): The ID of the entity to merge
  • data (Map<String, dynamic>): The data to deep merge

Returns: Operation - The merge operation

Example:

await db.transact([ db.merge(userId, { 'preferences': { 'theme': 'dark', 'notifications': {'email': false}, }, }), ]);

Create a link operation between entities.

Operation link(String fromId, String linkName, String toId)

Parameters:

  • fromId (String): The source entity ID
  • linkName (String): The name of the link relationship
  • toId (String): The target entity ID

Returns: Operation - The link operation

Example:

await db.transact([ db.link(userId, 'posts', postId), ]);

Create an unlink operation between entities.

Operation unlink(String fromId, String linkName, String toId)

Parameters:

  • fromId (String): The source entity ID
  • linkName (String): The name of the link relationship
  • toId (String): The target entity ID

Returns: Operation - The unlink operation

Example:

await db.transact([ db.unlink(userId, 'posts', postId), ]);

Transaction API (tx namespace)

tx

Access the new transaction API namespace for fluent operations.

TransactionNamespace get tx

Returns: TransactionNamespace - The transaction namespace

Example:

// Fluent API for complex operations await db.transact( db.tx['users'][userId] .update({'name': 'New Name'}) .link({'posts': [postId]}) .merge({ 'preferences': {'theme': 'dark'}, }) );

Utility Methods

id()

Generate a new UUID for entity IDs.

String id()

Returns: String - A new UUID string

Example:

final newId = db.id(); print('Generated ID: $newId'); // e.g., "123e4567-e89b-12d3-a456-426614174000" await db.transact([ ...db.create('items', { 'id': newId, 'name': 'New Item', }), ]);

lookup()

Create a lookup reference for referencing entities by attribute instead of ID.

LookupRef lookup(String entityType, String attribute, dynamic value)

Parameters:

  • entityType (String): The type of entity to lookup
  • attribute (String): The attribute to match against
  • value (dynamic): The value to match

Returns: LookupRef - A lookup reference object

Example:

// Reference user by email instead of ID await db.transact([ ...db.create('posts', { 'id': db.id(), 'title': 'Hello World', 'authorId': lookup('users', 'email', 'john@example.com'), }), ]); // Use in queries final posts = db.subscribeQuery({ 'posts': { 'where': { 'author': lookup('users', 'email', 'john@example.com'), }, }, });

Authentication Helpers

getAuth()

Get the current authentication state (one-time check).

AuthUser? getAuth()

Returns: AuthUser? - The current user, or null if not authenticated

Example:

final currentUser = db.getAuth(); if (currentUser != null) { print('Logged in as: ${currentUser.email}'); } else { print('Not logged in'); }

subscribeAuth()

Get a stream of authentication state changes.

Stream<AuthUser?> subscribeAuth()

Returns: Stream<AuthUser?> - A stream of auth user state

Example:

db.subscribeAuth().listen((user) { if (user != null) { print('User signed in: ${user.email}'); } else { print('User signed out'); } });

getAnonymousUserId()

Get or generate an anonymous user ID for presence and collaboration.

String getAnonymousUserId()

Returns: String - An anonymous user ID

Example:

final anonymousId = db.getAnonymousUserId(); final room = db.presence.joinRoom('public-room', initialPresence: { 'userId': anonymousId, 'userName': 'Guest ${anonymousId.substring(0, 4)}', });

Lifecycle Methods

dispose()

Clean up database resources and connections.

Future<void> dispose()

Returns: Future<void>

Example:

@override void dispose() { super.dispose(); // Clean up database when app is disposed db.dispose(); }

Error Handling

All InstantDB methods can throw InstantException for database-related errors:

try { await db.transact([ ...db.create('invalid', {}), // Missing required fields ]); } on InstantException catch (e) { print('InstantDB Error: ${e.code}'); print('Message: ${e.message}'); // Handle specific error types switch (e.code) { case 'validation_error': // Handle validation errors break; case 'network_error': // Handle network issues break; case 'auth_error': // Handle authentication errors break; } } catch (e) { print('Unexpected error: $e'); }

Complete Example

Here’s a complete example showing common InstantDB operations:

class TodoService { final InstantDB db; TodoService(this.db); // Get reactive todos Signal<QueryResult> getTodos({bool? completed}) { return db.subscribeQuery({ 'todos': { if (completed != null) 'where': {'completed': completed}, 'orderBy': {'createdAt': 'desc'}, }, }); } // Create a new todo Future<void> createTodo({ required String text, bool completed = false, }) async { await db.transact([ ...db.create('todos', { 'id': db.id(), 'text': text, 'completed': completed, 'createdAt': DateTime.now().millisecondsSinceEpoch, 'userId': db.auth.currentUser.value?.id, }), ]); } // Update todo using new tx API Future<void> updateTodo(String todoId, {String? text, bool? completed}) async { final updates = <String, dynamic>{}; if (text != null) updates['text'] = text; if (completed != null) updates['completed'] = completed; updates['updatedAt'] = DateTime.now().millisecondsSinceEpoch; await db.transact( db.tx['todos'][todoId].update(updates) ); } // Delete todo Future<void> deleteTodo(String todoId) async { await db.transact([db.delete(todoId)]); } // Get todos by user email (using lookup) Signal<QueryResult> getTodosByUser(String email) { return db.subscribeQuery({ 'todos': { 'where': { 'user': lookup('users', 'email', email), }, }, }); } // Bulk operations Future<void> markAllCompleted() async { final result = await db.queryOnce({ 'todos': {'where': {'completed': false}}, }); final todos = (result.data?['todos'] as List? ?? []) .cast<Map<String, dynamic>>(); final operations = todos.map((todo) => db.update(todo['id'], {'completed': true}) ).toList(); if (operations.isNotEmpty) { await db.transact(operations); } } }

Next Steps

Explore specific API areas: