Admin SDK
Database operations from the server using a Service Key. All operations bypass Access Rules.
The server-side database API is available in all Admin SDKs.
Setup
- JavaScript
- Dart/Flutter
- Kotlin
- Java
- Scala
- Python
- Go
- PHP
- Rust
- C#
- Ruby
- Elixir
import { createAdminClient } from '@edgebase/admin';
const admin = createAdminClient('https://my-app.edgebase.dev', {
serviceKey: process.env.EDGEBASE_SERVICE_KEY,
});
Inside App Functions, the URL and Service Key are detected from environment variables automatically:
const admin = createAdminClient();
import 'package:edgebase_admin/edgebase_admin.dart';
final admin = AdminEdgeBase(
'https://my-app.edgebase.dev',
serviceKey: Platform.environment['EDGEBASE_SERVICE_KEY']!,
);
import dev.edgebase.sdk.admin.AdminEdgeBase
val admin = AdminEdgeBase(
"https://my-app.edgebase.dev",
System.getenv("EDGEBASE_SERVICE_KEY")
)
import dev.edgebase.sdk.admin.*;
AdminEdgeBase admin = EdgeBase.admin(
"https://my-app.edgebase.dev",
System.getenv("EDGEBASE_SERVICE_KEY")
);
import dev.edgebase.sdk.scala.admin.AdminEdgeBase
val admin = AdminEdgeBase(
"https://my-app.edgebase.dev",
sys.env("EDGEBASE_SERVICE_KEY")
)
import os
from edgebase_admin import AdminClient
admin = AdminClient(
'https://my-app.edgebase.dev',
service_key=os.environ['EDGEBASE_SERVICE_KEY'],
)
import edgebase "github.com/edgebase/sdk-go"
admin := edgebase.NewAdminClient("https://my-app.edgebase.dev", os.Getenv("EDGEBASE_SERVICE_KEY"))
use EdgeBase\Admin\AdminClient;
$admin = new AdminClient('https://my-app.edgebase.dev', getenv('EDGEBASE_SERVICE_KEY'));
use edgebase_admin::EdgeBase;
let admin = EdgeBase::server(
"https://my-app.edgebase.dev",
&std::env::var("EDGEBASE_SERVICE_KEY").unwrap(),
)?;
using EdgeBase.Admin;
var admin = new AdminClient("https://my-app.edgebase.dev", Environment.GetEnvironmentVariable("EDGEBASE_SERVICE_KEY"));
require "edgebase_admin"
admin = EdgebaseAdmin::AdminClient.new(
"https://my-app.edgebase.dev",
service_key: ENV.fetch("EDGEBASE_SERVICE_KEY")
)
alias EdgeBaseAdmin
admin =
EdgeBaseAdmin.new("https://my-app.edgebase.dev",
service_key: System.fetch_env!("EDGEBASE_SERVICE_KEY")
)
Admin SDK requests authenticated with a Service Key bypass EdgeBase's app-level rate limits entirely, including global. This makes Admin SDK suitable for high-throughput server-to-server operations.
Use admin.db(namespace, id?) to select a DB block, then .table(name) to access a table:
admin.db('app') // single-instance DB block
admin.db('workspace', 'ws-456') // workspace-isolated DB block
admin.db('user', userId) // per-user DB block
Single-instance block names are just config keys. Older docs may show shared, but app, catalog, or any other descriptive name works the same way.
TypeScript Generics
Define an interface for your table and pass it as a type parameter to table<T>(). All operations will be fully typed:
interface Post {
id: string;
title: string;
content: string;
status: 'draft' | 'published' | 'archived';
views: number;
createdAt: string;
updatedAt: string;
}
const posts = admin.db('app').table<Post>('posts');
// All return types are now typed as Post
const post = await posts.getOne('post-id'); // Post
const result = await posts.getList(); // ListResult<Post>
const first = await posts.getFirst(); // Post | null
// Insert/update data is typed as Partial<Post>
await posts.insert({ title: 'Hello', content: '...', status: 'draft' });
await posts.update('post-id', { status: 'published' });
Error Handling
All SDK methods throw on failure — there is no { data, error } return pattern.
Error Structure
| Property | Type | Description |
|---|---|---|
status | number | HTTP status code |
message | string | Human-readable error message |
data | Record<string, { code, message }> | Per-field validation errors (optional) |
Common Error Codes
| Code | Name | When |
|---|---|---|
| 400 | Validation Error | Schema validation failed, batch limit exceeded |
| 401 | Unauthorized | Invalid Service Key |
| 403 | Forbidden | Operation not permitted |
| 404 | Not Found | Record or table doesn't exist |
- JavaScript
- Dart/Flutter
- Kotlin
- Java
- Scala
- Python
- Go
- PHP
- Rust
- C#
- Ruby
- Elixir
import { EdgeBaseError } from '@edgebase/core';
try {
await admin.db('app').table('posts').getOne('nonexistent');
} catch (error) {
if (error instanceof EdgeBaseError) {
console.error(error.status); // 404
console.error(error.message); // "Not found."
console.error(error.data); // undefined (or field errors for 400)
}
}
import 'package:edgebase_core/edgebase_core.dart';
try {
await admin.db('app').table('posts').getOne('nonexistent');
} on EdgeBaseError catch (e) {
print(e.status); // 404
print(e.message); // "Not found."
}
try {
val post = admin.db("app").table("posts").getOne("nonexistent")
} catch (e: EdgeBaseError) {
println(e.status) // 404
println(e.message) // "Not found."
}
try {
var post = admin.db("app").table("posts").getOne("nonexistent");
} catch (EdgeBaseError e) {
System.out.println(e.getStatus()); // 404
System.out.println(e.getMessage()); // "Not found."
}
import dev.edgebase.sdk.scala.core.EdgeBaseError
try {
admin.db("app").table("posts").getOne("nonexistent")
} catch {
case e: EdgeBaseError =>
println(e.statusCode) // 404
println(e.reason) // "Not found."
}
from edgebase_core.errors import EdgeBaseError
try:
admin.db('app').table('posts').get_one('nonexistent')
except EdgeBaseError as e:
print(e.status_code) # 404
print(e.message) # "Not found."
post, err := client.DB("app", "").Table("posts").GetOne(ctx, "nonexistent")
if err != nil {
fmt.Println(err) // "HTTP 404: Not found."
}
use EdgeBase\EdgeBaseException;
try {
$admin->db('app')->table('posts')->getOne('nonexistent');
} catch (EdgeBaseException $e) {
echo $e->getStatusCode(); // 404
echo $e->getMessage(); // "Not found."
}
match admin.db("app").table("posts").get_one("nonexistent").await {
Ok(post) => println!("{:?}", post),
Err(e) => eprintln!("{}", e), // "HTTP 404: Not found."
}
try {
var post = await admin.Db("app").Table("posts").GetOneAsync("nonexistent");
} catch (EdgeBaseException e) {
Console.WriteLine(e.StatusCode); // 404
Console.WriteLine(e.Message); // "Not found."
}
begin
admin.db("app").table("posts").get_one("nonexistent")
rescue EdgebaseCore::EdgeBaseError => e
puts e.status_code
puts e.message
end
alias EdgeBaseCore.{DbRef, Error, TableRef}
try do
admin
|> EdgeBaseAdmin.db("app")
|> DbRef.table("posts")
|> TableRef.get_one!("nonexistent")
rescue
e in Error ->
IO.inspect(e.status_code) # 404
IO.puts(e.message) # "Not found."
end
Insert
- JavaScript
- Dart/Flutter
- Kotlin
- Java
- Scala
- Python
- Go
- PHP
- Rust
- C#
- Ruby
- Elixir
const post = await admin.db('app').table('posts').insert({
title: 'Hello World',
content: 'My first post.',
status: 'published',
});
// post.id → "0192d3a4-..." (UUID v7, auto-generated)
final post = await admin.db('app').table('posts').insert({
'title': 'Hello World',
'content': 'My first post.',
'status': 'published',
});
val post = admin.db("app").table("posts").insert(mapOf(
"title" to "Hello World",
"content" to "My first post.",
"status" to "published"
))
Map<String, Object> post = admin.db("app").table("posts").insert(Map.of(
"title", "Hello World",
"content", "My first post.",
"status", "published"
));
val post = admin.db("app").table("posts").insert(Map(
"title" -> "Hello World",
"content" -> "My first post.",
"status" -> "published",
))
post = admin.db('app').table('posts').insert({
'title': 'Hello World',
'content': 'My first post.',
'status': 'published',
})
post, err := client.DB("app", "").Table("posts").Insert(ctx, map[string]any{
"title": "Hello World",
"content": "My first post.",
"status": "published",
})
$post = $admin->db('app')->table('posts')->insert([
'title' => 'Hello World',
'content' => 'My first post.',
'status' => 'published',
]);
let post = admin.db("app").table("posts").insert(&json!({
"title": "Hello World",
"content": "My first post.",
"status": "published",
})).await?;
var post = await admin.Db("app").Table("posts").InsertAsync(new() {
["title"] = "Hello World",
["content"] = "My first post.",
["status"] = "published",
});
post = admin.db("app").table("posts").insert({
"title" => "Hello World",
"content" => "My first post.",
"status" => "published",
})
alias EdgeBaseCore.{DbRef, TableRef}
post =
admin
|> EdgeBaseAdmin.db("app")
|> DbRef.table("posts")
|> TableRef.insert!(%{
"title" => "Hello World",
"content" => "My first post.",
"status" => "published"
})
Read
Get a single record
- JavaScript
- Dart/Flutter
- Kotlin
- Java
- Scala
- Python
- Go
- PHP
- Rust
- C#
- Ruby
- Elixir
const post = await admin.db('app').table('posts').getOne('record-id');
final post = await admin.db('app').table('posts').getOne('record-id');
val post = admin.db("app").table("posts").getOne("record-id")
Map<String, Object> post = admin.db("app").table("posts").getOne("record-id");
val post = admin.db("app").table("posts").getOne("record-id")
post = admin.db('app').table('posts').get_one('record-id')
post, err := client.DB("app", "").Table("posts").GetOne(ctx, "record-id")
$post = $admin->db('app')->table('posts')->getOne('record-id');
let post = admin.db("app").table("posts").get_one("record-id").await?;
var post = await admin.Db("app").Table("posts").GetOneAsync("record-id");
post = admin.db("app").table("posts").get_one("record-id")
alias EdgeBaseCore.{DbRef, TableRef}
post =
admin
|> EdgeBaseAdmin.db("app")
|> DbRef.table("posts")
|> TableRef.get_one!("record-id")
JS, Python, Dart, Kotlin, Java, Scala, Ruby, and Elixir SDKs also support the doc() pattern for single-record operations:
const ref = admin.db('app').table('posts').doc('record-id');
await ref.get(); // Same as getOne('record-id')
await ref.update({...}); // Same as update('record-id', {...})
await ref.delete(); // Same as delete('record-id')
ref.onSnapshot(callback); // Realtime subscription for this document
Get First Match
Retrieve the first record matching query conditions. Returns null if no records match.
- JavaScript
- Dart/Flutter
- Kotlin
- Java
- Scala
- Python
- Go
- PHP
- Rust
- C#
- Ruby
- Elixir
const user = await admin.db('app').table('users')
.where('email', '==', 'june@example.com')
.getFirst();
// user → T | null
final user = await admin.db('app').table('users')
.where('email', '==', 'june@example.com')
.getFirst();
// user → Map<String, dynamic>?
val user = admin.db("app").table("users")
.where("email", "==", "june@example.com")
.getFirst()
// user → Map<String, Any>?
Map<String, Object> user = admin.db("app").table("users")
.where("email", "==", "june@example.com")
.getFirst();
// user → null if not found
val user = admin.db("app").table("users")
.where("email", "==", "june@example.com")
.getFirst()
// user → Option[Map[String, Any]]
user = admin.db('app').table('users') \
.where('email', '==', 'june@example.com') \
.get_first()
# user → dict | None
user, err := client.DB("app", "").Table("users").
Where("email", "==", "june@example.com").
GetFirst(ctx)
// user → map[string]any (nil if not found)
$user = $admin->db('app')->table('users')
->where('email', '==', 'june@example.com')
->getFirst();
// $user → ?array
let user = admin.db("app").table("users")
.where_("email", "==", "june@example.com")
.get_first()
.await?;
// user → Option<T>
var user = await admin.Db("app").Table("users")
.Where("email", "==", "june@example.com")
.GetFirstAsync();
// user → T?
user = admin.db("app").table("users")
.where("email", "==", "june@example.com")
.get_first
alias EdgeBaseCore.{DbRef, TableRef}
user =
admin
|> EdgeBaseAdmin.db("app")
|> DbRef.table("users")
|> TableRef.where("email", "==", "june@example.com")
|> TableRef.get_first!()
# user → map() | nil
Internally calls
.limit(1).getList()and returns the first item. No special server endpoint needed.
List records
- JavaScript
- Dart/Flutter
- Kotlin
- Java
- Scala
- Python
- Go
- PHP
- Rust
- C#
- Ruby
- Elixir
const result = await admin.db('app').table('posts')
.orderBy('createdAt', 'desc')
.limit(20)
.getList();
// result.items → Post[]
// result.total → 150
// result.page → 1
final result = await admin.db('app').table('posts')
.orderBy('createdAt', desc: true)
.limit(20)
.getList();
val result = admin.db("app").table("posts")
.orderBy("createdAt", "desc")
.limit(20)
.getList()
ListResult result = admin.db("app").table("posts")
.orderBy("createdAt", "desc")
.limit(20)
.getList();
val result = admin.db("app").table("posts")
.orderBy("createdAt", "desc")
.limit(20)
.getList()
result = admin.db('app').table('posts') \
.order_by('createdAt', 'desc') \
.limit(20) \
.get_list()
result, err := client.DB("app", "").Table("posts").
OrderBy("createdAt", "desc").
Limit(20).
GetList(ctx)
$result = $admin->db('app')->table('posts')
->orderBy('createdAt', 'desc')
->limit(20)
->getList();
let result = admin.db("app").table("posts")
.order_by("createdAt", "desc")
.limit(20)
.get_list()
.await?;
var result = await admin.Db("app").Table("posts")
.OrderBy("createdAt", "desc")
.Limit(20)
.GetListAsync();
result = admin.db("app").table("posts")
.order_by("createdAt", "desc")
.limit(20)
.get_list
alias EdgeBaseCore.{DbRef, TableRef}
result =
admin
|> EdgeBaseAdmin.db("app")
|> DbRef.table("posts")
|> TableRef.order_by("createdAt", "desc")
|> TableRef.limit(20)
|> TableRef.get_list!()
Update
- JavaScript
- Dart/Flutter
- Kotlin
- Java
- Scala
- Python
- Go
- PHP
- Rust
- C#
- Ruby
- Elixir
await admin.db('app').table('posts').update('record-id', {
title: 'Updated Title',
status: 'published',
});
Field Operators
import { increment, deleteField } from '@edgebase/core';
await admin.db('app').table('posts').update('record-id', {
views: increment(1), // Atomic increment
tempField: deleteField(), // Set to NULL
});
await admin.db('app').table('posts').update('record-id', {
'title': 'Updated Title',
'views': EdgeBase.increment(1),
'tempField': EdgeBase.deleteField(),
});
admin.db("app").table("posts").update("record-id", mapOf(
"title" to "Updated Title",
"views" to EdgeBase.increment(1),
"tempField" to EdgeBase.deleteField()
))
admin.db("app").table("posts").update("record-id", Map.of(
"title", "Updated Title",
"views", EdgeBaseFieldOps.increment(1),
"tempField", EdgeBaseFieldOps.deleteField()
));
import dev.edgebase.sdk.core.FieldOps
admin.db("app").table("posts").update("record-id", Map(
"title" -> "Updated Title",
"views" -> FieldOps.increment(1),
"tempField" -> FieldOps.deleteField(),
))
admin.db('app').table('posts').update('record-id', {
'title': 'Updated Title',
'views': eb.increment(1),
'temp_field': eb.delete_field(),
})
updated, err := client.DB("app", "").Table("posts").Update(ctx, "record-id", map[string]any{
"title": "Updated Title",
"views": edgebase.Increment(1),
"tempField": edgebase.DeleteField(),
})
$updated = $admin->db('app')->table('posts')->update('record-id', [
'title' => 'Updated Title',
'views' => FieldOps::increment(1),
'tempField' => FieldOps::deleteField(),
]);
let updated = admin.db("app").table("posts").update("record-id", &json!({
"title": "Updated Title",
"views": field_ops::increment(1),
"tempField": field_ops::delete_field(),
})).await?;
var updated = await admin.Db("app").Table("posts").UpdateAsync("record-id", new() {
["title"] = "Updated Title",
["views"] = FieldOps.Increment(1),
["tempField"] = FieldOps.DeleteField(),
});
updated = admin.db("app").table("posts").update("record-id", {
"title" => "Updated Title",
"views" => EdgebaseCore::FieldOps.increment(1),
"tempField" => EdgebaseCore::FieldOps.delete_field,
})
alias EdgeBaseCore.{DbRef, FieldOps, TableRef}
admin
|> EdgeBaseAdmin.db("app")
|> DbRef.table("posts")
|> TableRef.update!("record-id", %{
"title" => "Updated Title",
"views" => FieldOps.increment(1),
"tempField" => FieldOps.delete_field()
})
Delete
- JavaScript
- Dart/Flutter
- Kotlin
- Java
- Scala
- Python
- Go
- PHP
- Rust
- C#
- Ruby
- Elixir
await admin.db('app').table('posts').delete('record-id');
await admin.db('app').table('posts').delete('record-id');
admin.db("app").table("posts").delete("record-id")
admin.db("app").table("posts").delete("record-id");
admin.db("app").table("posts").delete("record-id")
admin.db('app').table('posts').delete('record-id')
err := client.DB("app", "").Table("posts").Delete(ctx, "record-id")
$admin->db('app')->table('posts')->delete('record-id');
admin.db("app").table("posts").delete("record-id").await?;
await admin.Db("app").Table("posts").DeleteAsync("record-id");
admin.db("app").table("posts").delete("record-id")
alias EdgeBaseCore.{DbRef, TableRef}
admin
|> EdgeBaseAdmin.db("app")
|> DbRef.table("posts")
|> TableRef.delete!("record-id")
Queries
Filtering
Use where() to filter records. Multiple where() calls are combined with AND. Available operators: ==, !=, >, <, >=, <=, contains, in, not in.
Use .or() to combine conditions with OR logic. Conditions inside .or() are joined with OR, while multiple .where() calls remain AND. A maximum of 5 conditions are allowed inside a single .or() group.
// OR across different fields
const results = await admin.db('app').table('posts')
.or(q => q.where('status', '==', 'draft').where('authorId', '==', userId))
.getList();
// AND + OR combined
const results = await admin.db('app').table('posts')
.where('createdAt', '>', '2025-01-01')
.or(q => q.where('status', '==', 'draft').where('status', '==', 'archived'))
.getList();
For same-field OR, the in operator is more efficient: where('status', 'in', ['draft', 'review']).
- JavaScript
- Dart/Flutter
- Kotlin
- Java
- Scala
- Python
- Go
- PHP
- Rust
- C#
- Ruby
- Elixir
// Simple filter
const published = await admin.db('app').table('posts')
.where('status', '==', 'published')
.getList();
// Multiple filters (AND)
const myPosts = await admin.db('app').table('posts')
.where('authorId', '==', currentUser.id)
.where('status', '==', 'published')
.getList();
// Contains (partial text match)
const results = await admin.db('app').table('posts')
.where('title', 'contains', 'tutorial')
.getList();
// In (match any of the values)
const featured = await admin.db('app').table('posts')
.where('status', 'in', ['published', 'featured'])
.getList();
final published = await admin.db('app').table('posts')
.where('status', '==', 'published')
.getList();
final myPosts = await admin.db('app').table('posts')
.where('authorId', '==', currentUser.id)
.where('status', '==', 'published')
.getList();
val published = admin.db("app").table("posts")
.where("status", "==", "published")
.getList()
ListResult published = admin.db("app").table("posts")
.where("status", "==", "published")
.getList();
val published = admin.db("app").table("posts")
.where("status", "==", "published")
.getList()
published = admin.db('app').table('posts') \
.where('status', '==', 'published') \
.get_list()
published, err := client.DB("app", "").Table("posts").
Where("status", "==", "published").
GetList(ctx)
$published = $admin->db('app')->table('posts')
->where('status', '==', 'published')
->getList();
let published = admin.db("app").table("posts")
.where_("status", "==", "published")
.get_list()
.await?;
var published = await admin.Db("app").Table("posts")
.Where("status", "==", "published")
.GetListAsync();
published = admin.db("app").table("posts")
.where("status", "==", "published")
.get_list
alias EdgeBaseCore.{DbRef, TableRef}
published =
admin
|> EdgeBaseAdmin.db("app")
|> DbRef.table("posts")
|> TableRef.where("status", "==", "published")
|> TableRef.get_list!()
Sorting
- JavaScript
- Dart/Flutter
- Kotlin
- Java
- Scala
- Python
- Go
- PHP
- Rust
- C#
- Ruby
- Elixir
// Single sort
const latest = await admin.db('app').table('posts')
.orderBy('createdAt', 'desc')
.getList();
// Multi-sort
const sorted = await admin.db('app').table('posts')
.orderBy('status', 'asc')
.orderBy('createdAt', 'desc')
.getList();
final latest = await admin.db('app').table('posts')
.orderBy('createdAt', desc: true)
.getList();
val latest = admin.db("app").table("posts")
.orderBy("createdAt", "desc")
.getList()
ListResult latest = admin.db("app").table("posts")
.orderBy("createdAt", "desc")
.getList();
val latest = admin.db("app").table("posts")
.orderBy("createdAt", "desc")
.getList()
latest = admin.db('app').table('posts') \
.order_by('createdAt', 'desc') \
.get_list()
latest, err := client.DB("app", "").Table("posts").
OrderBy("createdAt", "desc").
GetList(ctx)
$latest = $admin->db('app')->table('posts')
->orderBy('createdAt', 'desc')
->getList();
let latest = admin.db("app").table("posts")
.order_by("createdAt", "desc")
.get_list()
.await?;
var latest = await admin.Db("app").Table("posts")
.OrderBy("createdAt", "desc")
.GetListAsync();
latest = admin.db("app").table("posts")
.order_by("createdAt", "desc")
.get_list
alias EdgeBaseCore.{DbRef, TableRef}
latest =
admin
|> EdgeBaseAdmin.db("app")
|> DbRef.table("posts")
|> TableRef.order_by("createdAt", "desc")
|> TableRef.get_list!()
Pagination
Offset Pagination
// Using offset
const page2 = await admin.db('app').table('posts')
.limit(20)
.offset(20)
.getList();
// Using page (alias for offset-based pagination)
const page3 = await admin.db('app').table('posts')
.page(3)
.limit(20)
.getList();
// Response: { items: [...], total: 150, page: 3, perPage: 20 }
page(n) and after(cursor)/before(cursor) are mutually exclusive. You cannot use both in the same query.
Cursor Pagination
For better performance with large datasets, use cursor pagination with UUID v7 keys:
const firstPage = await admin.db('app').table('posts')
.limit(20)
.getList();
// Next page using cursor (forward)
const nextPage = await admin.db('app').table('posts')
.limit(20)
.after(firstPage.items[firstPage.items.length - 1].id)
.getList();
// Previous page using cursor (backward)
const prevPage = await admin.db('app').table('posts')
.limit(20)
.before(nextPage.items[0].id)
.getList();
// Cursor response format:
// { items: [...], cursor: "last-item-id", hasMore: true }
Count
Get the count of records without fetching them:
- JavaScript
- Dart/Flutter
- Kotlin
- Java
- Scala
- Python
- Go
- PHP
- Rust
- C#
- Ruby
- Elixir
const total = await admin.db('app').table('posts').count();
// total → 150
// With filter
const published = await admin.db('app').table('posts')
.where('status', '==', 'published')
.count();
final total = await admin.db('app').table('posts').count();
final published = await admin.db('app').table('posts')
.where('status', '==', 'published')
.count();
val total = admin.db("app").table("posts").count()
int total = admin.db("app").table("posts").count();
val total = admin.db("app").table("posts").count()
val published = admin.db("app").table("posts")
.where("status", "==", "published")
.count()
total = admin.db('app').table('posts').count()
total, err := client.DB("app", "").Table("posts").Count(ctx)
$total = $admin->db('app')->table('posts')->count();
let total = admin.db("app").table("posts").count().await?;
int total = await admin.Db("app").Table("posts").CountAsync();
total = admin.db("app").table("posts").count
published = admin.db("app").table("posts")
.where("status", "==", "published")
.count
alias EdgeBaseCore.{DbRef, TableRef}
posts =
admin
|> EdgeBaseAdmin.db("app")
|> DbRef.table("posts")
total = TableRef.count!(posts)
published = posts |> TableRef.where("status", "==", "published") |> TableRef.count!()
Batch Operations
insertMany
Create multiple records in a single atomic transaction (all-or-nothing):
- JavaScript
- Dart/Flutter
- Kotlin
- Java
- Scala
- Python
- Go
- PHP
- Rust
- C#
- Ruby
- Elixir
const posts = await admin.db('app').table('posts').insertMany([
{ title: 'Post 1', status: 'published' },
{ title: 'Post 2', status: 'draft' },
{ title: 'Post 3', status: 'published' },
]);
// All succeed or all fail (single transaction)
final posts = await admin.db('app').table('posts').insertMany([
{'title': 'Post 1', 'status': 'published'},
{'title': 'Post 2', 'status': 'draft'},
{'title': 'Post 3', 'status': 'published'},
]);
val posts = admin.db("app").table("posts").insertMany(listOf(
mapOf("title" to "Post 1", "status" to "published"),
mapOf("title" to "Post 2", "status" to "draft"),
))
BatchResult posts = admin.db("app").table("posts").insertMany(List.of(
Map.of("title", "Post 1", "status", "published"),
Map.of("title", "Post 2", "status", "draft")
));
val posts = admin.db("app").table("posts").insertMany(Seq(
Map("title" -> "Post 1", "status" -> "published"),
Map("title" -> "Post 2", "status" -> "draft"),
))
posts = admin.db('app').table('posts').insert_many([
{'title': 'Post 1', 'status': 'published'},
{'title': 'Post 2', 'status': 'draft'},
])
posts, err := client.DB("app", "").Table("posts").InsertMany(ctx, []map[string]any{
{"title": "Post 1", "status": "published"},
{"title": "Post 2", "status": "draft"},
})
$posts = $admin->db('app')->table('posts')->insertMany([
['title' => 'Post 1', 'status' => 'published'],
['title' => 'Post 2', 'status' => 'draft'],
]);
let posts = admin.db("app").table("posts").insert_many(vec![
json!({"title": "Post 1", "status": "published"}),
json!({"title": "Post 2", "status": "draft"}),
]).await?;
var posts = await admin.Db("app").Table("posts").InsertManyAsync(new[] {
new Dictionary<string, object> { ["title"] = "Post 1", ["status"] = "published" },
new Dictionary<string, object> { ["title"] = "Post 2", ["status"] = "draft" },
});
posts = admin.db("app").table("posts").insert_many([
{ "title" => "Post 1", "status" => "published" },
{ "title" => "Post 2", "status" => "draft" },
])
alias EdgeBaseCore.{DbRef, TableRef}
posts =
admin
|> EdgeBaseAdmin.db("app")
|> DbRef.table("posts")
|> TableRef.insert_many!([
%{"title" => "Post 1", "status" => "published"},
%{"title" => "Post 2", "status" => "draft"}
])
updateMany
Update all records matching a filter condition:
The Go Admin SDK documents insertMany, but updateMany and deleteMany are not exposed on the current Go TableRef yet, so those tabs are intentionally omitted here.
- JavaScript
- Dart/Flutter
- Kotlin
- Java
- Scala
- Python
- PHP
- Rust
- C#
- Ruby
- Elixir
const result = await admin.db('app').table('posts')
.where('status', '==', 'draft')
.updateMany({ status: 'archived' });
// result.totalProcessed → 42, result.totalSucceeded → 42
final result = await admin.db('app').table('posts')
.where('status', '==', 'draft')
.updateMany({'status': 'archived'});
val result = admin.db("app").table("posts")
.where("status", "==", "draft")
.updateMany(mapOf("status" to "archived"))
BatchResult result = admin.db("app").table("posts")
.where("status", "==", "draft")
.updateMany(Map.of("status", "archived"));
val result = admin.db("app").table("posts")
.where("status", "==", "draft")
.updateMany(Map("status" -> "archived"))
result = admin.db('app').table('posts') \
.where('status', '==', 'draft') \
.update_many({'status': 'archived'})
$result = $admin->db('app')->table('posts')
->where('status', '==', 'draft')
->updateMany(['status' => 'archived']);
let result = admin.db("app").table("posts")
.where_("status", "==", "draft")
.update_many(&json!({"status": "archived"}))
.await?;
var result = await admin.Db("app").Table("posts")
.Where("status", "==", "draft")
.UpdateManyAsync(new() { ["status"] = "archived" });
result = admin.db("app").table("posts")
.where("status", "==", "draft")
.update_many({ "status" => "archived" })
alias EdgeBaseCore.{DbRef, TableRef}
result =
admin
|> EdgeBaseAdmin.db("app")
|> DbRef.table("posts")
|> TableRef.where("status", "==", "draft")
|> TableRef.update_many!(%{"status" => "archived"})
deleteMany
Delete all records matching a filter condition:
- JavaScript
- Dart/Flutter
- Kotlin
- Java
- Scala
- Python
- PHP
- Rust
- C#
- Ruby
- Elixir
const result = await admin.db('app').table('posts')
.where('status', '==', 'archived')
.deleteMany();
// result.totalProcessed → 15, result.totalSucceeded → 15
final result = await admin.db('app').table('posts')
.where('status', '==', 'archived')
.deleteMany();
val result = admin.db("app").table("posts")
.where("status", "==", "archived")
.deleteMany()
BatchResult result = admin.db("app").table("posts")
.where("status", "==", "archived")
.deleteMany();
val result = admin.db("app").table("posts")
.where("status", "==", "archived")
.deleteMany()
result = admin.db('app').table('posts') \
.where('status', '==', 'archived') \
.delete_many()
$result = $admin->db('app')->table('posts')
->where('status', '==', 'archived')
->deleteMany();
let result = admin.db("app").table("posts")
.where_("status", "==", "archived")
.delete_many()
.await?;
var result = await admin.Db("app").Table("posts")
.Where("status", "==", "archived")
.DeleteManyAsync();
result = admin.db("app").table("posts")
.where("status", "==", "archived")
.delete_many
alias EdgeBaseCore.{DbRef, TableRef}
result =
admin
|> EdgeBaseAdmin.db("app")
|> DbRef.table("posts")
|> TableRef.where("status", "==", "archived")
|> TableRef.delete_many!()
upsertMany
Batch upsert — insert or update multiple records atomically:
await admin.db('app').table('settings').upsertMany([
{ id: 'theme', value: 'dark' },
{ id: 'lang', value: 'ko' },
]);
You can also upsert by a unique field using conflictTarget:
await admin.db('app').table('categories').upsertMany(
[
{ name: 'Tech', slug: 'tech' },
{ name: 'Science', slug: 'science' },
],
{ conflictTarget: 'slug' }
);
- Maximum 500 items per server batch call. The REST API returns
400if a single request exceeds 500 items. - SDK auto-chunking: When
insertManyreceives more than 500 items, the SDK automatically splits them into 500-item chunks and sends them sequentially. Each chunk is an independent transaction, so partial failures are possible. insertMany(≤ 500) — All-or-nothing (single transaction)updateMany / deleteMany— Each batch is an independent transactionupsertMany(≤ 500) — All-or-nothing (single transaction)
The Go SDK does not yet support updateMany, deleteMany, or upsertMany. Use individual Update/Delete calls in a loop, or handle batch operations via App Functions.
Full-Text Search
Search across text fields using FTS5. Requires fts to be enabled on the table in your config:
// edgebase.config.ts
posts: {
schema: { /* ... */ },
fts: ['title', 'content'], // Enable FTS on these fields
}
- JavaScript
- Dart/Flutter
- Kotlin
- Java
- Scala
- Python
- Go
- PHP
- Rust
- C#
- Ruby
- Elixir
const results = await admin.db('app').table('posts')
.search('typescript tutorial')
.limit(20)
.getList();
// results.items → ranked by relevance
// results.items[0].highlight → { title: "...<mark>TypeScript</mark> <mark>Tutorial</mark>..." }
final results = await admin.db('app').table('posts')
.search('typescript tutorial')
.limit(20)
.getList();
val results = admin.db("app").table("posts")
.search("typescript tutorial")
.limit(20)
.getList()
ListResult results = admin.db("app").table("posts")
.search("typescript tutorial")
.limit(20)
.getList();
val results = admin.db("app").table("posts")
.search("typescript tutorial")
.limit(20)
.getList()
results = admin.db('app').table('posts') \
.search('typescript tutorial') \
.limit(20) \
.get_list()
results, err := client.DB("app", "").Table("posts").
Search("typescript tutorial").
Limit(20).
GetList(ctx)
$results = $admin->db('app')->table('posts')
->search('typescript tutorial')
->limit(20)
->getList();
let results = admin.db("app").table("posts")
.search("typescript tutorial")
.limit(20)
.get_list()
.await?;
var results = await admin.Db("app").Table("posts")
.Search("typescript tutorial")
.Limit(20)
.GetListAsync();
results = admin.db("app").table("posts")
.search("typescript tutorial")
.limit(20)
.get_list
alias EdgeBaseCore.{DbRef, TableRef}
results =
admin
|> EdgeBaseAdmin.db("app")
|> DbRef.table("posts")
|> TableRef.search("typescript tutorial")
|> TableRef.limit(20)
|> TableRef.get_list!()
.search() can be combined with .where(), .orderBy(), and .limit() like any other query. Uses trigram tokenizer for CJK language support.
For more details, see Advanced — Full-Text Search.
Raw SQL (App Functions Only)
Inside App Functions, you can execute raw SQL using admin.sql():
// functions/analytics.ts
import { defineFunction } from '@edgebase/shared';
export default defineFunction({
trigger: { type: 'http', path: '/api/functions/analytics-top-authors', method: 'GET' },
handler: async (context) => {
const topAuthors = await context.admin.sql(
'posts',
'SELECT authorId, COUNT(*) as postCount FROM posts WHERE status = ? GROUP BY authorId ORDER BY postCount DESC LIMIT ?',
['published', 10]
);
return Response.json(topAuthors);
},
});
The db.sql tagged template is also available as an alternative syntax. Both forms are fully supported:
// Tagged template
const rows = await context.admin.db('app').sql`SELECT * FROM posts WHERE status = ${'published'}`;
// Parameterized (recommended for dynamic queries)
const rows = await context.admin.sql('posts', 'SELECT * FROM posts WHERE status = ?', ['published']);