Ambiten

Ambiten v1.2.0: Stronger Schema Enforcement and a More Predictable Runtime

Ambiten continues to evolve around a simple idea: infrastructure should make application development more predictable, not more complicated.

With Ambiten v1.2.0, the focus has been on strengthening some of the runtime relationships developers depend on most: the connection between schemas and models, document validation, and the lifecycle of an initialized Ambiten runtime.

These changes may appear small when viewed individually, but together they make the runtime more coherent and give developers stronger guarantees as applications grow.


From Schema Registration To Schema Enforcement

Ambiten has always provided schema and model abstractions, but v1.2.0 strengthens the relationship between them.

When using AmbitenBootstrapFactory, a schema can be defined alongside the model configuration:

import {
  AmbitenBootstrapFactory
} from "@ambiten/core";

export async function run() {
  return AmbitenBootstrapFactory.create({
    config: {
      schema: {
        username: {
          type: "string",
          required: true,
          unique: true
        },
        password: {
          type: "string",
          required: true
        },
        email: {
          type: "string",
          required: true
        }
      },

      model: {
        collectionName: "users"
      }
    }
  });
}

During bootstrap, Ambiten creates the runtime schema and connects it to the initialized model. That relationship now extends directly into document operations.

When a model creates a document, the registered AmbitenSchema participates in validation before the document reaches MongoDB. This means a mistake such as:

await userModel.create({
  usernmae: "john",
  password: "secret",
  email: "john@example.com"
});

can be rejected because usernmae is not part of the registered schema. Instead of allowing an incorrectly structured document to silently enter the database, Ambiten can surface the problem before persistence.


Stronger Document Contracts

MongoDB's flexible document model is one of its strengths, but flexibility does not have to mean giving up application-level guarantees.

With v1.2.0, Ambiten's schema layer can participate more actively in enforcing those guarantees. Depending on the schema definition, validation can now account for unknown document properties, required properties, expected field types, and custom synchronous or asynchronous validators.

For example:

const schema = runtime.getSchema();

schema.validator("username", (value) => {
  return value.length >= 3;
});

Custom validators remain available, but they now complement the structural contract described by the schema rather than operating independently from it.

The runtime flow becomes much clearer:

Schema Definition
      |
AmbitenSchema
      |
AmbitenModel
      |
Document Validation
      |
MongoDB

The model knows the schema it belongs to, and the schema has an active role in determining whether a document is valid.


A Cleaner Bootstrap Experience

One of the goals of AmbitenBootstrapFactory is to reduce the amount of infrastructure wiring application code has to perform manually. Developers describe the runtime they want:

const runtime =
  await AmbitenBootstrapFactory.create({
    config: {
      schema: {
        username: {
          type: "string",
          required: true
        },
        email: {
          type: "string",
          required: true
        }
      },

      model: {
        collectionName: "users"
      }
    }
  });

The initialized resources are then available through the runtime:

const userModel = runtime.getModel();
const userSchema = runtime.getSchema();

Application code does not have to repeatedly reconnect the schema, collection, and model. That responsibility belongs to bootstrap. The application can concentrate on using the initialized runtime.


More Predictable Runtime Connection Hooks

Ambiten v1.2.0 also refines the runtime connection lifecycle. Applications can register an onConnect callback:

runtime.onConnect(() => {
  console.log("Ambiten connected");
});

The behavior is designed to be predictable. If the runtime is still waiting for its connection, the callback can execute once the runtime becomes connected. If initialization has already completed by the time the callback is registered, Ambiten can execute it immediately instead of making the application wait for an event that has already happened.

This makes patterns such as the following straightforward:

runtime.onConnect(() => {
  const client = runtime.getMongoClient();

  console.log(
    "MongoDB client ready:",
    Boolean(client)
  );
});

For applications that bootstrap before starting their HTTP server, this provides a simple way to confirm runtime readiness.


A Runtime That Exposes What Has Already Been Initialized

The AmbitenRuntime remains the primary runtime-facing contract after bootstrap. A typical application can initialize Ambiten once:

const runtime = await run();

and then access capabilities such as:

runtime.getMongoClient();
runtime.getModel();
runtime.getSchema();
runtime.getLogger();
runtime.getGraphQL();
runtime.getGCRunner();

alongside runtime operations including:

runtime.registerMultiTenancy(...);
runtime.cache(...);
runtime.invalidateCache(...);
runtime.onConnect(...);
runtime.shutdown();

The distinction is intentional:

Bootstrap constructs and configures the environment.
The runtime exposes and operates the initialized environment.

Keeping those responsibilities separate allows application code to remain relatively small even as infrastructure requirements increase.


Why These Changes Matter

Ambiten is being developed for applications where MongoDB access eventually becomes only one part of a larger runtime problem.

As systems grow, developers begin dealing with tenant identity, request context, transaction continuity, runtime lifecycle, connection management, logging, caching, validation, observability, and adapter integration.

Ambiten's goal is to give these concerns a common runtime foundation rather than requiring every application layer to coordinate them independently.

Strengthening the schema-model relationship in v1.2.0 is part of that direction. A schema should not simply exist because it was registered during startup. A model that belongs to that schema should be able to rely on it when handling documents.

Likewise, a runtime connection hook should reflect the actual state of the runtime rather than requiring the application to reason about when initialization happened. These are the kinds of guarantees v1.2.0 continues to build.


Getting Started With Ambiten v1.2.0

Ambiten can be installed from npm:

npm install @ambiten/core

The documentation is available at docs.ambiten.dev.

The documentation covers the runtime, context propagation, multi-tenancy, transactions, adapters, and other parts of the Ambiten ecosystem.

A new tutorial series is also underway, starting from building an Ambiten-powered API and progressively moving into the runtime concepts behind it. The goal is not only to show which APIs are available, but to explain why the runtime exists and how its different pieces work together.


Moving Forward

Ambiten v1.2.0 is another step toward making the runtime more consistent from initialization through persistence.

Schemas now have a stronger relationship with the models that consume them. Document validation happens closer to the runtime boundary where it belongs. Connection lifecycle behavior is more predictable. And the Bootstrap Factory continues to reduce the amount of infrastructure code developers need to coordinate themselves.

There is still much more to explore. The upcoming tutorials will go deeper into Ambiten's context-aware runtime, multi-tenancy, transactions, adapters, and bootstrap workflow.

For now, v1.2.0 strengthens the foundation those capabilities build upon.

Ambiten: context-aware, multi-tenant and transaction-safe runtime infrastructure for MongoDB applications.