Tyranid supports a lifecycle for its models to help model data workflows and lifecycle within Tyranid models.


Initialization code should be placed in the collection Component.boot.

Any sort of code that needs to run when the application servers are first launched should be placed here.

The Tyranid bootstrapping framework also supports dealing with complex bootstrapping dependencies and orderings -- including circular dependencies.


Events are the primary place to handle most lifecycle and workflow concerns.

On-change handlers provide a place to do additional tasks when documents are created or modified. For example, updating ElasticSearch indices, updating permissions, creation of related documents, and so on.

On-remove handlers provide a place to perform any tasks that are needed when a document is removed. For example, removing documents from external indices, removing dependent documents, and so on.


In addition to standard built-in validations like required, minlength, and so on (see field definitions for a full list), Fields can have also an (optionally asynchronous) handler defined for each field. This can be used to perform field-level validations that are triggered while interacting with a client-side form.

For example, the following validation could be provided which front-end controls would invoke when a user focuses out of an email field:

      email: {
        is: 'email',
        required: true,
        async validate() {
          if ( {
            return (
              (await User.exists({
                query: {
                  email: {
                    $regex: '^' + escapeRegex( + '$',
                    $options: 'i'
                  _id: { $ne: this._id }
              })) && `Sorry, that email is already used: ${}`


Implementing a collection Collection.fromClient handler provides the primary place to perform updates to collection instances after being created or edited on the client.

It can also be used as a place to provide additional security checks and verifications as all updates from client will go through this method before being committed to the database.

This method handler can optionally be async so that security checks and other asynchronous code can be called.