Skip to content

Repository files navigation

⚡ BLite Server

License: AGPL v3Build StatusVersionBLite Engine

BLite Server 2.0.0 is a high-performance, self-hosted database server built on top of the BLite 5.0.0 embedded engine.
It exposes BLite's full capabilities over three interfaces — a gRPC endpoint for the .NET SDK, a REST API for cross-language access, and a Blazor Studio web UI for administration — all hosted on ASP.NET Core / Kestrel.


Endpoints

EndpointDefault PortProtocolPurpose
gRPC2626HTTP/2, TLSBLite.Client SDK, high-throughput streaming
REST API2627HTTP/1.1 + HTTP/2Cross-language clients, tooling, CI
Studio2628HTTP/1.1 + HTTP/2Blazor Server admin UI

Architecture

┌──────────────────────────────────────────────────────────────────────┐
│ BLite.Server │
│ │
│ ┌──────────────────┐ ┌──────────────────────┐ ┌────────────────┐ │
│ │ gRPC :2626 │ │ REST /api/v1 :2627 │ │ Studio :2628 │ │
│ │ DynamicService │ │ Minimal API endpoints│ │ Blazor Server │ │
│ │ DocumentService │ │ PermissionFilter │ │ StudioService │ │
│ │ AdminService │ │ RestAuthFilter │ │ StudioSession │ │
│ │ MetadataService │ │ OpenAPI / Scalar │ └───────┬────────┘ │
│ │ TransactionSvc │ └───────────┬───────────┘ │ │
│ │ KvService │ │ │ │
│ └────────┬─────────┘ │ │ │
│ └──────────────┬─────────┘ │ │
│ ▼ │ │
│ ┌─────────────────┐◄───────────────────────┘ │
│ │ EngineRegistry │ │
│ │ (singleton) │ │
│ └────────┬────────┘ │
│ │ one BLiteEngine per database │
│ ▼ │
│ ┌─────────────────┐ │
│ │ BLiteEngine │ (sibling repo: BLite) │
│ │ + Collections │ │
│ │ + KvStore │ │
│ └─────────────────┘ │
└──────────────────────────────────────────────────────────────────────┘

Projects

ProjectDescription
BLite.ProtoShared .proto contracts + QueryDescriptor (MessagePack)
BLite.ServerASP.NET Core host — gRPC services, REST API, Blazor Studio, auth, observability
BLite.Client.NET client SDK — RemoteDynamicCollection, RemoteCollection<TId,T>, RemoteKvStore

gRPC Services

All gRPC calls require an x-api-key header.
The server enforces per-collection permission checks and transparent namespace isolation.

serviceDynamicService {
// CRUDrpcInsert (InsertRequest) returns (InsertResponse);
rpcFindById (FindByIdRequest) returns (DocumentResponse);
rpcUpdate (UpdateRequest) returns (MutationResponse);
rpcDelete (DeleteRequest) returns (MutationResponse);
// Streaming query + vector searchrpcQuery (QueryRequest) returns (streamDocumentResponse);
rpcVectorSearch (VectorSearchRequest) returns (streamDocumentResponse);
// Bulk operationsrpcInsertBulk (BulkInsertRequest) returns (BulkInsertResponse);
rpcUpdateBulk (BulkUpdateRequest) returns (BulkMutationResponse);
rpcDeleteBulk (BulkDeleteRequest) returns (BulkMutationResponse);
// Collection managementrpcListCollections (Empty) returns (CollectionListResponse);
rpcDropCollection (DropCollectionRequest) returns (MutationResponse);
rpcCreateIndex (CreateIndexRequest) returns (MutationResponse);
rpcDropIndex (DropIndexRequest) returns (MutationResponse);
rpcListIndexes (CollectionRequest) returns (ListIndexesResponse);
// VectorSource (embedding worker)rpcSetVectorSource (SetVectorSourceRequest) returns (MutationResponse);
rpcGetVectorSource (CollectionRequest) returns (GetVectorSourceResponse);
// TimeSeriesrpcConfigureTimeSeries (ConfigureTimeSeriesRequest) returns (MutationResponse);
rpcGetTimeSeriesInfo (CollectionRequest) returns (TimeSeriesResponse);
rpcForcePrune (CollectionRequest) returns (MutationResponse);
// SchemarpcGetSchema (CollectionRequest) returns (CollectionSchemaResponse);
rpcSetSchema (SetSchemaRequest) returns (MutationResponse);
}
serviceDocumentService {
// Typed (BSON payload) path — mirrors DynamicService for typed collectionsrpcQuery (QueryRequest) returns (streamTypedDocumentResponse);
rpcInsert (TypedInsertRequest) returns (InsertResponse);
rpcUpdate (TypedUpdateRequest) returns (MutationResponse);
rpcDelete (DeleteRequest) returns (MutationResponse);
rpcInsertBulk (TypedBulkInsertRequest) returns (BulkInsertResponse);
}
serviceAdminService {
rpcCreateUser (CreateUserRequest) returns (CreateUserResponse);
rpcRevokeUser (UsernameRequest) returns (MutationResponse);
rpcRotateKey (UsernameRequest) returns (RotateKeyResponse);
rpcListUsers (Empty) returns (ListUsersResponse);
rpcUpdatePerms (UpdatePermsRequest) returns (MutationResponse);
rpcProvisionTenant (ProvisionTenantRequest) returns (ProvisionTenantResponse);
rpcDeprovisionTenant (DeprovisionTenantRequest) returns (DeprovisionTenantResponse);
rpcListTenants (Empty) returns (ListTenantsResponse);
}
serviceTransactionService {
rpcBegin (BeginTransactionRequest) returns (BeginTransactionResponse);
rpcCommit (TransactionRequest) returns (MutationResponse);
rpcRollback (TransactionRequest) returns (MutationResponse);
}
serviceKvService {
// ReadrpcGet (KvGetRequest) returns (KvGetResponse);
rpcExists (KvKeyRequest) returns (KvExistsResponse);
rpcScanKeys (KvScanRequest) returns (KvScanResponse);
// WriterpcSet (KvSetRequest) returns (MutationResponse);
rpcDelete (KvDeleteRequest) returns (MutationResponse);
rpcRefresh (KvRefreshRequest) returns (MutationResponse); // extend TTLrpcBatch (KvBatchRequest) returns (KvBatchResponse);
// AdminrpcPurgeExpired (KvDbRequest) returns (KvPurgeResponse);
}

All write RPCs accept an optional transaction_id field.


BLite 5.0.0 — New Features

BLite Server 2.0.0 runs on BLite 5.0.0 and exposes the following new engine capabilities:

FeatureEngine APIServer exposure
AES-256-GCM encryption at restCryptoOptions on engine builderReported in GDPR inspection; transparent to clients
Audit TrailIBLiteAuditSink, BLiteMetrics/metrics REST endpoint; engine-level metrics
GDPR primitivesGdprEngineExtensions, SubjectQuery, [PersonalData]/gdpr/inspect, /gdpr/export-subject REST + Studio GDPR page
Generalized Retention PolicyHasRetentionPolicy on any typed collectionReported in GDPR inspection per-collection
Secure EraseHasSecureErase — zero-overwrites on deleteTransparent to clients
Multi-Process WALPageFileConfig.EnableMultiProcessAccessConfigured per engine at startup
VacuumAsyncengine.VacuumAsync()POST /{dbId}/vacuum REST endpoint + Studio GDPR page

REST API

Base path: /api/v1. All endpoints require x-api-key or Authorization: Bearer <key>.
Interactive docs available at /scalar when Studio is enabled.

Databases (tenant management)

MethodPathDescription
GET/databasesList all tenant databases
POST/databasesProvision a new tenant database
DELETE/databases/{dbId}Deprovision a tenant database
GET/databases/{dbId}/backupDownload a hot backup as a ZIP file

Collections

MethodPathDescription
GET/{dbId}/collectionsList collections
POST/{dbId}/collectionsCreate a collection
DELETE/{dbId}/{collection}Drop a collection
GET/{dbId}/{collection}/vectorsourceGet VectorSource config
PUT/{dbId}/{collection}/vectorsourceSet VectorSource config
DELETE/{dbId}/{collection}/vectorsourceClear VectorSource config
GET/{dbId}/{collection}/timeseriesGet TimeSeries config
PUT/{dbId}/{collection}/timeseriesConfigure TimeSeries + retention
POST/{dbId}/{collection}/timeseries/pruneForce retention prune
GET/{dbId}/{collection}/schemaGet collection schema
PUT/{dbId}/{collection}/schemaSet / append schema version

Documents

MethodPathDescription
GET/{dbId}/{collection}/documentsList documents (paginated)
POST/{dbId}/{collection}/documentsInsert a document
GET/{dbId}/{collection}/documents/{id}Get document by ID
PUT/{dbId}/{collection}/documents/{id}Replace document
DELETE/{dbId}/{collection}/documents/{id}Delete document
POST/{dbId}/{collection}/documents/vector-searchkNN vector search

BLQL Query

MethodPathDescription
POST/{dbId}/{collection}/queryBLQL filter + sort query (JSON body)
GET/{dbId}/{collection}/queryBLQL query via query-string params
POST/{dbId}/{collection}/countCount documents matching a filter

Key-Value Store

MethodPathDescription
GET/{dbId}/kvScan keys (optional ?prefix=)
GET/{dbId}/kv/{key}Get value (Base64-encoded)
PUT/{dbId}/kv/{key}Set value ({ value, ttlMs? })
DELETE/{dbId}/kv/{key}Delete a key
PATCH/{dbId}/kv/{key}Refresh TTL ({ ttlMs })
POST/{dbId}/kv/purgePurge all expired entries
POST/{dbId}/kv/batchAtomic batch set/delete

Users

MethodPathDescription
GET/usersList all users
POST/usersCreate a user
DELETE/users/{username}Delete a user
PUT/users/{username}/permissionsReplace user permissions

GDPR (requires Admin permission)

MethodPathDescription
GET/{dbId}/gdpr/inspectArt. 30 inspection report: encryption, audit, per-collection personal-data fields, retention policies
POST/{dbId}/{collection}/gdpr/export-subjectExport all documents matching a field/value pair as a JSON file (Art. 15/20)

Body for export-subject: { "fieldName": "email", "fieldValue": "alice@example.com" }

Metrics (requires Admin permission)

MethodPathDescription
GET/metricsAggregate metrics across all active engines (read/write/delete counts, sizes)
GET/{dbId}/metricsMetrics for a specific tenant database

Vacuum (requires Admin permission)

MethodPathDescription
POST/{dbId}/vacuumCompact the database file and reclaim free pages

BLite.Client SDK

awaitusingvarclient=newBLiteClient(newBLiteClientOptions{Host="myserver",Port=2626,ApiKey="blt_...",UseTls=true});// Schema-less collectionvarsensors=client.GetDynamicCollection("sensors");varid=awaitsensors.InsertAsync(newBsonDocument{["temp"]=22.5});awaitforeach(vardocinsensors.QueryAsync(descriptor))Console.WriteLine(doc);// Typed collection (requires [BLiteMapper])varusers=client.GetCollection<ObjectId,User>(newUserMapper());awaitusers.InsertAsync(newUser{Name="Alice",Age=30});varresult=awaitusers.AsQueryable().Where(u =>u.Age>25).OrderBy(u =>u.Name).ToListAsync();// Explicit transactionawaitusingvartx=awaitclient.BeginTransactionAsync();awaitsensors.InsertAsync(doc,tx);awaittx.CommitAsync();// Key-Value storeawaitclient.Kv.SetAsync("session:xyz",Encoding.UTF8.GetBytes("data"),ttl:TimeSpan.FromHours(1));varbytes=awaitclient.Kv.GetAsync("session:xyz");varcount=awaitclient.Kv.BatchAsync(b =>b.Set("a",Encoding.UTF8.GetBytes("1")).Delete("b"));// AdminvarapiKey=awaitclient.Admin.CreateUserAsync("alice",namespace:null,permissions:[newUserPermission{Collection="orders",Ops=BLiteOperation.Write}]);awaitclient.Admin.ProvisionTenantAsync("tenant-42");

Studio

The Blazor Studio is a built-in administration UI served from the same process.
Enable it in appsettings.json:

"Studio": { "Enabled": true },
"Kestrel": {
"Endpoints": {
"Grpc": { "Url": "https://*:2626", "Protocols": "Http2" },
"Rest": { "Url": "https://*:2627", "Protocols": "Http1AndHttp2" },
"Studio": { "Url": "https://*:2628", "Protocols": "Http1AndHttp2" }
}
}

Studio pages:

PagePathDescription
Dashboard/Server uptime, version, tenant/user counts
Tenants/tenantsProvision / deprovision tenant databases, download backups
Users/usersCreate, revoke, rotate keys, manage permissions
Collections/collectionsBrowse, create, drop collections; insert JSON documents
Collection detail/collection/{name}Indexes, VectorSource, TimeSeries, Schema tabs
Documents/documents/{name}Browse, edit, delete documents; BLQL query
Key-Value/kvBrowse keys, set/edit/delete entries, purge expired
Embedding/embeddingLoad ONNX model, test embeddings, cosine-similarity sandbox
GDPR/gdprArt. 30 inspection (encryption, audit, personal-data fields, retention), subject export (Art. 15/20), Vacuum

First startup navigates to /setup to create the root admin user.


Authentication & Multi-tenancy

Every request must carry an x-api-key header (or Authorization: Bearer <key> for REST).

Permissions ([Flags] enum — composable):

FlagAllowed operations
QueryFindById, Query, VectorSearch, ScanKeys, Get, Exists
InsertInsert, InsertBulk, KV Set
UpdateUpdate, UpdateBulk, KV Refresh, KV Batch
DeleteDelete, DeleteBulk, KV Delete
DropDropCollection
AdminAll of the above + user management + tenant management + PurgeExpired

Namespace isolation — users with a Namespace field operate inside a transparent prefix.
Physical name: "<namespace>:<logical_name>". Always resolved via NamespaceResolver.Resolve.

Database isolation — users with a DatabaseId are restricted to one tenant engine.


QueryDescriptor

Expression trees are serialized as a QueryDescriptor (MessagePack) sent in the query_descriptor bytes field:

publicsealedclassQueryDescriptor{publicstringCollection{get;set;}publicFilterNode?Where{get;set;}// BinaryFilter | LogicalFilterpublicProjectionSpec?Select{get;set;}publicList<SortSpec>OrderBy{get;set;}publicint?Skip{get;set;}publicint?Take{get;set;}}

The server rebuilds native BLite predicates from the descriptor — T is never instantiated on the server.


Transactions

1. TransactionService.Begin → receives transaction_id (UUID)
2. Pass transaction_id in any write RPC → writes are buffered, not auto-committed
3. TransactionService.Commit or Rollback

At most one transaction per database at a time (enforced by SemaphoreSlim(1,1)).
Sessions idle longer than Transactions:TimeoutSeconds (default: 60 s) are rolled back automatically.


Observability

Built-in OpenTelemetry support:

  • Traces — every gRPC RPC generates a span via TelemetryInterceptor
  • Metricsblite.server.rpc.total, blite.server.rpc.duration, blite.server.documents.streamed, blite.server.active_transactions
  • Exporters — Console (dev) + OTLP/gRPC (Jaeger, Grafana, Datadog, …)
"Telemetry": {
"Enabled": true,
"ServiceName": "blite-server",
"Otlp": { "Endpoint": "http://localhost:4317" }
}

Getting Started

dotnet run --project src/BLite.Server

On first run, navigate to https://localhost:2628/setup to create the root admin user.

ServiceURL
gRPChttps://localhost:2626
REST APIhttps://localhost:2627/api/v1
OpenAPI (Scalar)https://localhost:2627/scalar
Studiohttps://localhost:2628

License

Licensed under the GNU Affero General Public License v3.0 (AGPL-3.0).
See LICENSE for the full text.

The AGPL-3.0 requires that any modified version of this software made available over a network also makes its source code available.
For a commercial license without this restriction, please contact the authors.


Related Projects

About

The BLite Server

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages