Reactive Scala Driver for MongoDB
Asynchronous & Non-Blocking
Connect to the database
The first thing you need, is to create a new
Then you can connect to a MongoDB server.
MongoDriver instance manages the shared resources (e.g. the actor system for the asynchronous processing); A connection manages a pool of network channels.
In general, a
MongoDriver or a
MongoConnection should not be instantiated more than once.
You can provide a list of one or more servers, the driver will guess if it’s a standalone server or a replica set configuration. Even with one replica node, the driver will probe for other nodes and add them automatically.
Some options can be provided while creating a connection.
The following options can be used with
MongoConnectionOptions to configure the connection behaviour.
authSource: DEPRECATED since 0.13, see
authMode: DEPRECATED since 0.14, see
authenticationDatabase: (optional) The database source for authentication credentials.
authenticationMechanism: (optional) The authentication mechanism, by default set to
scram-sha1for SCRAM-SHA-1. Can be configured with:
SSL & certificates:
sslEnabled: DEPRECATED, see
ssl: (optional) It enables the SSL support for the connection (
true|false, default is
sslAllowsInvalidCert: (optional) If
sslEnabledis true, this one indicates whether to accept invalid certificates (e.g. self-signed) (
true|false, default is
keyStore: (optional) An URI to a key store (e.g.
keyStorePassword: (optional) If
keyStoreis set, then provides the password to load it (if required).
keyStoreType: (optional) If
keyStoreis set, indicates the type of the store.
ssl is needed if the MongoDB server is requiring SSL (
mongod --sslMode requireSSL). The related option
sslAllowsInvalidCert is required if the server allows invalid certificate (
SNI is supported for the SSL connection.
Network, timeouts & failover:
connectTimeoutMS: The number of milliseconds to wait for a connection to be established before giving up.
maxIdleTimeMS: The maximum number of milliseconds that a connection can remain idle in the pool before being removed and closed.
rm.tcpNoDelay: TCPNoDelay boolean flag (
rm.keepAlive: TCP KeepAlive boolean flag (
rm.nbChannelsPerNode: Number of channels (connections) per node.
rm.monitorRefreshMS): The interval (in milliseconds) used by the ReactiveMongo monitor to refresh the node set (default: 10s); The minimal value is 100ms.
rm.failover: The default failover strategy.
default: The default/minimal strategy, with 10 retries with an initial delay of 100ms and a delay factor of
retry count * 1.25(100ms .. 125ms, 250ms, 375ms, 500ms, 625ms, 750ms, 875ms, 1s, 1125ms, 1250ms).
remote: The strategy for remote MongoDB node(s); Same as default but with 16 retries.
strict: A more strict strategy; Same as default but with only 5 retries.
<delay>:<retries>x<factor>: The definition of a custom strategy;
Read isolation & consistency:
writeConcern: The default write concern (default:
wset to 0, journaling off (
fsyncoff, no timeout.
wset to 1, journaling off,
fsyncoff, no timeout.
wset to 1, journaling on,
fsyncoff, no timeout.
writeConcernW: The option
wfor the default write concern. If
writeConcernis specified, its
wwill be replaced by this
majority: The write operations have to be propagated to the majority of voting nodes.
0: Disable the acknowledgement.
1: Acknowledgement from the standalone server or primary one.
- positive integer: Acknowledgement by at least the specified number of replica set members.
- tag: Acknowledgement by the member of the replica set matching the given tag.
writeConcernJ: Toggle journaling on the default write concern. Of
writeConcernis specified, its
jwill be replaced by this
writeConcernJboolean flag (
writeConcernTimeout: The time limit (in milliseconds) for the default write concern. If
writeConcernis specified, its timeout is replaced by this one.
readPreference: The default read preference (
primary|primaryPreferred|secondary|secondaryPreferred|nearest) (default is
nearest: Do not consider whether nodes are primary or secondary, but select one according how fast it is to answer an
isMasterrequest (ping time).
If the connection pool is defined by an URI, then the options can be given after the
Connecting to a Replica Set
ReactiveMongo provides support for replica sets as follows.
- The driver will detect if it is connected to a replica set.
- It will probe for the other nodes in the set and connect to them.
- It will detect when the primary has changed and guess which is the new one.
- It will allow running queries on secondaries, if allowed by the read preference (See the MongoDB documentation for more details about querying secondary nodes).
Connecting to a replica set is pretty much the same as connecting to a unique server. You may have notice that the connection argument is a
List[String], so more than one node can be specified.
There is no obligation to give all the nodes in the replica set. Actually, just one of them is required. ReactiveMongo will ask the nodes it can reach for the addresses of the other nodes in the replica set. Obviously it is better to give at least 2 or more nodes, in case of unavailability of one node at the start of the application.
Using many connection instances
In that case, you will get different connection pools. This is useful when your application has to connect to two or more independent MongoDB nodes (i.e. that do not belong to the same replica set), or different replica sets.
There are two ways to give ReactiveMongo your credentials.
It can be done using
connection function with an URI allows to indicates the credentials in this URI.
There is also a
authenticate function for the database references.
Like any other operation in ReactiveMongo, authentication is done asynchronously.
Connect Using MongoDB URI
You can also give the connection information as a URI:
If credentials and the database name are included in the URI, ReactiveMongo will authenticate the connections on that database.
The following example is using a connection to asynchronously resolve a database.
Note that DNS seedlist is supported, using
mongodb+srv:// scheme in the connection URI.
ReactiveMongo is internally using (as a shaded dependency) Netty 4.1.x.
It makes possible to use the native optimization of Netty. To do so, the
reactivemongo-shaded-native must be added as runtime dependency, with the appropriate version.
In order to make sure such optimization is loaded, you can enable the
INFO level for the logger
reactivemongo.core.netty.Pack (e.g. in your logback configuration), then check for a log entry containing “NettyPack”.
16:03:43.098 ReactiveMongo INFO [r.c.n.Pack] :: Instantiated NettyPack(class reactivemongo.io.netty.channel.kqueue.KQueueSocketChannel)
MongoConnection stands for a pool of connections.
Do not get confused here: a
MongoConnection is a logical connection, not a physical one (not a network channel); It’s actually a connection pool. By default, a
MongoConnection creates 10 physical network channels to each node; It can be tuned this by setting the
rm.nbChannelsPerNode options (see the connection options.
They manage two different things.
MongoDriver holds the actor system, and
MongoConnection the references to the actors. This is useful because it enables to work with many different single nodes or replica sets. Thus, your application can communicate with different replica sets or single nodes, with only one
MongoConnection involve creation costs:
- the driver creates a new
- and the connection, will connect to the servers (creating network channels).
It is also a good idea to store the driver and connection instances to reuse them.
On the contrary,
Collection are just plain objects that store references and nothing else.
Getting such references is lightweight, and calling
db.collection(..) may be done many times without any performance hit.
It’s generally a good practice not to assign the database and collection references to
lazy val), as it’s better to get a fresh reference each time, to automatically recover from any previous issues (e.g. network failure).
Virtual Private Network (VPN):
When connecting to a MongoDB replica set over a VPN, if using IP addresses instead of host names to configure the connection nodes, then it’s possible that the nodes are discovered with host names that are only known within the remote network, and so not usable from the driver/client side.
The bellow errors may indicate there is a connectivity and/or network issue.
Primary not available
reactivemongo.core.actors.Exceptions$PrimaryUnavailableException: MongoError['No primary node is available! ...']
- In logging: “The primary is unavailable, is there a network problem?” (not critical if no application error occurs)
Node set not reachable
reactivemongo.core.actors.Exceptions$NodeSetNotReachable: MongoError['The node set can not be reached! Please check your network connectivity ...']
- In logging: “The entire node set is unreachable, is there a network problem?” (not critical if no application error occurs)
If one of the error is seen, first retry/refresh to check it wasn’t a temporary system/network issue. If the issue is then reproduced, the following can be checked.
Are the DB nodes accessible from the node running the application?
- Using the MongoDB Shell:
mongo primary-host:primary-port/name-of-database(replace the primary host & port and the database name with the same used in the ReactiveMongo connection URI).
- With the SBT Playground, using the same connection URI.
- Possible causes: Broken network, authentication issue (before 0.13, MONGODB-CR is the default mode; See the
authenticationMechanismoption), SSL issue (check the
Is the connection URI used with ReactiveMongo valid?
If using the Play module, the
strictUri setting can be enabled (e.g.
If calling directly the function
strictUri parameter can be set to
Connect without any non mandatory options (e.g.
connectTimeoutMS), using the SBT Playground to try the alternative URI.
Using the following code, make sure there is no authentication issue.
Connecting to a MongoDB ReplicaSet, is status ok?
- Using the MongoDB Shell to connect to the primary node, execute
With the ReactiveMongo logging enabled, more details can be found (see a trace example thereafter).
The JMX module can be used to check how the node set is seen by the driver.