Skip to main content
Version: 3.6

Advanced Configuration

Entity Discovery

You can either provide array of entity instances via entities, or let the ORM look up your entities in selected folders.

entities: [Author, Book, Publisher, BookTag],

When using entitiesDirs, you can optionally provide also set of directories with TS source files, that will be used to look up missing types (see more at Metadata Providers).

The entitiesDirsTs option is used only with the default TsMorphMetadataProvider. By default, all your source files will be scanned, based on your tsconfig.json.

entitiesDirs: ['./dist/modules/users/entities', './dist/modules/projects/entities'],
// optional, more specific paths will speed up the discovery
entitiesDirsTs: ['./src/modules/users/entities', './src/modules/projects/entities'],
// optionally you can override the base directory (defaults to `process.cwd()`)
baseDir: process.cwd(),

By default, TsMorphMetadataProvider is used that analyses your entity source files. You can use ReflectMetadataProvider if you do not want the source file analyses to happen. If you aim to use plain JavaScript instead of TypeScript, use the JavaScriptMetadataProvider.

You can also implement your own metadata provider and use it instead. To do so, extend the MetadataProvider class.

metadataProvider: ReflectMetadataProvider,

There are also some additional options how you can adjust the discovery process:

discovery: {
warnWhenNoEntities: false, // by default, discovery throws when no entity is processed
requireEntitiesArray: true, // force usage of `entities` instead of `entitiesDirs`
alwaysAnalyseProperties: false, // do not analyse properties when not needed (with ts-morph)

// you can explicitly specify the path to your tsconfig.json (used only when `entitiesDirsTs` is not provided)
tsConfigPath: string,

If you disable discovery.alwaysAnalyseProperties option, you will need to explicitly provide nullable and wrappedReference parameters (where applicable).

Read more about this in Metadata Providers sections.


To select driver, you can either use type option, or provide the driver class reference.

typedriver namedependencynote
mongoMongoDrivermongodb^3.3.4default driver
mysqlMySqlDrivermysql2^2.0.0compatible with MariaDB
mariadbMariaDbDrivermariadb^2.0.0compatible with MySQL

Driver and connection implementations are not directly exported from mikro-orm module. You can import them from mikro-orm/dist/drivers.

You can pass additional options to the underlying driver (e.g. mysql2) via driverOptions. The object will be deeply merged, overriding all internally used options.

import { MySqlDriver } from 'mikro-orm/dist/drivers/MySqlDriver';

driver: MySqlDriver,
driverOptions: { connection: { timezone: '+02:00' } },

From v3.5.1 you can also set the timezone directly in the ORM configuration:

type: 'mysql',
timezone: '+02:00',


Each platform (driver) provides default connection string, you can override it as a whole through clientUrl, or partially through one of following options:

export interface ConnectionOptions {
dbName?: string;
name?: string; // for logging only (when replicas are used)
clientUrl?: string;
host?: string;
port?: number;
user?: string;
password?: string;
multipleStatements?: boolean; // for mysql driver
pool?: PoolConfig; // provided by `knex`

Following table shows default client connection strings:

typedefault connection url

To set up read replicas, you can use replicas option. You can provide only those parts of the ConnectionOptions interface, they will be used to override the master connection options.

type: 'mysql',
dbName: 'my_db_name',
user: 'write-user',
host: '',
port: 3306,
replicas: [
{ user: 'read-user-1', host: '', port: 3307 },
{ user: 'read-user-2', host: '', port: 3308 },
{ user: 'read-user-3', host: '', port: 3309 },

Read more about this in Installation and Read Connections sections.


Since MikroORM v3, default value for autoFlush is false. That means you need to call em.flush() yourself to persist changes into database. You can still change this via ORM's options to ease the transition but generally it is not recommended as it can cause unwanted small transactions being created around each persist.

autoFlush: true,

await orm.em.persist(new Entity()); // flushed
orm.em.persist(new Entity(), false); // you can still use second parameter to disable auto-flushing

Read more about this in Entity Manager docs.

Naming Strategy

When mapping your entities to database tables and columns, their names will be defined by naming strategy. There are 3 basic naming strategies you can choose from:

  • UnderscoreNamingStrategy - default of all SQL drivers
  • MongoNamingStrategy - default of MongoDriver
  • EntityCaseNamingStrategy - uses unchanged entity and property names

You can also define your own custom NamingStrategy implementation.

namingStrategy: EntityCaseNamingStrategy,

Read more about this in Naming Strategy section.

Auto-join of 1:1 owners

By default, owning side of 1:1 relation will be auto-joined when you select the inverse side so we can have the reference to it. You can disable this behaviour via autoJoinOneToOneOwner configuration toggle.

autoJoinOneToOneOwner: false,

Propagation of 1:1 and m:1 owners

MikroORM defines getter and setter for every owning side of m:1 and 1:1 relation. This is then used for propagation of changes to the inverse side of bi-directional relations.

const author = new Author('n', 'e');
const book = new Book('t'); = author;
console.log(author.books.contains(book)); // true

You can disable this behaviour via propagateToOneOwner option.

propagateToOneOwner: false,

Forcing UTC Timezone

Use forceUtcTimezone option to force the Dates to be saved in UTC in datetime columns without timezone. It works for MySQL (datetime type) and PostgreSQL (timestamp type). SQLite does this by default.

forceUtcTimezone: true,

Custom Hydrator

Hydrator is responsible for assigning values from the database to entities. You can implement your custom Hydrator (by extending the abstract Hydrator class):

hydrator: MyCustomHydrator,

Custom Repository

You can also register custom base repository (for all entities where you do not specify customRepository) globally:

You can still use entity specific repositories in combination with global base repository.

entityRepository: CustomBaseRepository,

Read more about this in Repositories section.

Strict Mode

MikroORM will validate your properties before actual persisting happens. It will try to fix wrong data types for you automatically. If automatic conversion fails, it will throw an error. You can enable strict mode to disable this feature and let ORM throw errors instead. Validation is triggered when persisting the entity.

strict: true,

Read more about this in Property Validation section.

Debugging & Logging

You can enable logging with debug option. Either set it to true to log everything, or provide array of 'query' | 'query-params' | 'discovery' | 'info' namespaces.

logger: (message: string) =>, // defaults to `console.log()`
debug: true, // or provide array like `['query', 'query-params']`
highlight: false, // defaults to true
highlightTheme: { ... }, // you can also provide custom highlight there

Read more about this in Debugging section.

Custom Fail Handler

When no entity is found during em.findOneOrFail() call, new Error() will be thrown. You can customize how the Error instance is created via findOneOrFailHandler:

findOneOrFailHandler: (entityName: string, where: Dictionary | IPrimaryKey) => {
return new NotFoundException(`${entityName} not found!`);

Read more about this in Entity Manager docs.


Under the migrations namespace, you can adjust how the integrated migrations support works. Following example shows all possible options and their defaults:

migrations: {
tableName: 'mikro_orm_migrations', // migrations table name
path: process.cwd() + '/migrations', // path to folder with migration files
pattern: /^[\w-]+\d+\.ts$/, // how to match migration files
transactional: true, // run each migration inside transaction
disableForeignKeys: true, // try to disable foreign_key_checks (or equivalent)
allOrNothing: true, // run all migrations in current batch in master transaction
emit: 'ts', // migration generation mode

Read more about this in Migrations section.


By default, metadata discovery results are cached. You can either disable caching, or adjust how it works. Following example shows all possible options and their defaults:

cache: {
enabled: true,
pretty: false, // allows to pretty print the JSON cache
adapter: FileCacheAdapter, // you can provide your own implementation here, e.g. with redis
options: { cacheDir: process.cwd() + '/temp' }, // options will be passed to the constructor of `adapter` class

Read more about this in Metadata Cache section.