User-managed mode & replication
|
This section documents the current Solr line (10.0; 9.10.x the maintained 9.x branch), written and verified against the Apache Solr Reference Guide. No specific patch version is pinned. Some capabilities (the Solr Operator on Kubernetes, the package-manager ecosystem, Learning To Rank model training, and expert plugin development) are linked, not documented in depth. This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production. This section’s bibliography lists the reference material consulted while preparing these pages. |
User-managed mode (the older name is "standalone") is the Solr cluster type with no ZooKeeper
and no collection concept: every deployment unit is a core, created and administered one node at a
time, as introduced in Core concepts &
architecture. Nothing coordinates cores across nodes automatically, so redundancy and horizontal
search fan-out have to be built by hand — classic leader/follower index replication over the
/replication handler, and distributed search across a shards parameter you assemble yourself.
This page covers both mechanisms and where this older model still earns its place over
SolrCloud.
What user-managed mode is (and isn’t)
A user-managed core behaves exactly like any other core — same solrconfig.xml, same schema, same
/select and /update handlers — it simply has no ZooKeeper ensemble watching it, no collection
name, and no shard/replica bookkeeping. Nothing elects a leader, nothing reroutes a write when a node
disappears, and nothing reshards an index that has outgrown one machine: all three become manual
operator work, covered in the rest of this page.
# No -z / ZooKeeper flag: this node knows nothing about any other node.
bin/solr start --user-managed
# A bare core -- no -s (shards) or -rf (replication factor), because neither concept exists here.
bin/solr create_core -c books_core
The document and field model, the request-handler/search-component/query-parser pipeline, and near-real-time search via commits are identical in both cluster types — see Core concepts & architecture. What differs is covered below, and summarized end to end in Solr Cluster Types.
Leader/follower index replication
Redundancy in user-managed mode is index replication: one core (the leader) accepts writes and
periodically ships its Lucene index files, verbatim, to one or more other cores (the followers),
which serve read traffic from that copy. It is configured entirely through the ReplicationHandler,
registered under /replication in solrconfig.xml — there is no bin/solr flag for it. This is the
mechanism the Reference Guide used to call master/slave replication; the current documentation and
this page use leader/follower throughout, and the old terms survive only in some pre-9.x
configuration examples and log messages.
<!-- solrconfig.xml on the LEADER core -->
<requestHandler name="/replication" class="solr.ReplicationHandler">
<lst name="leader">
<str name="replicateAfter">commit</str>
<str name="replicateAfter">startup</str>
<str name="backupAfter">optimize</str>
<str name="confFiles">schema.xml,stopwords.txt,synonyms.txt</str>
</lst>
</requestHandler>
<!-- solrconfig.xml on a FOLLOWER core -->
<requestHandler name="/replication" class="solr.ReplicationHandler">
<lst name="follower">
<str name="leaderUrl">http://solr-leader:8983/solr/books_core</str>
<str name="pollInterval">00:00:20</str>
<str name="httpConnTimeout">5000</str>
<str name="httpReadTimeout">10000</str>
</lst>
</requestHandler>
replicateAfter decides when the leader makes a new index snapshot available (on every hard
commit, on optimize, on core startup); confFiles lists which config files ride along, because
followers otherwise only pull index data, not solrconfig.xml/schema changes. A follower’s
pollInterval sets how often it asks the leader whether a newer index version exists; when one does,
it pulls the changed segment files only (Lucene segments are immutable, so replication is
incremental after the first full copy) and opens a new searcher over them.
The same /replication handler is the operational surface for both roles — inspect status, force a
pull, or manage backups directly:
# Leader: the index version followers compare against.
curl "http://solr-leader:8983/solr/books_core/replication?command=indexversion"
# Follower: current status -- is it in sync, when did it last poll, any errors.
curl "http://solr-leader:8983/solr/books_core/replication?command=details"
# Follower: force an immediate pull instead of waiting for the next pollInterval.
curl "http://follower-1:8983/solr/books_core/replication?command=fetchindex"
# Leader: take a full backup of the current index to disk.
curl "http://solr-leader:8983/solr/books_core/replication?command=backup"
# Leader: temporarily stop serving replication (e.g. during maintenance).
curl "http://solr-leader:8983/solr/books_core/replication?command=disablereplication"
curl "http://solr-leader:8983/solr/books_core/replication?command=enablereplication"
# https://solr.apache.org/guide/solr/latest/deployment-guide/user-managed-index-replication.html
Failover is not automatic: if the leader core goes down, followers keep serving their last-replicated
copy read-only, but nothing promotes a follower to leader and nothing redirects writes — an operator
(or external tooling) has to repoint writes and reconfigure roles by hand. That single point of
write failure is the main reason SolrCloud, where a replica is elected leader automatically, is the
default recommendation; see
User-Managed
Index Replication for the full command reference (abortfetch, filelist, restore,
deletebackup, HTTP basic-auth options, and more).
Distributed search across user-managed cores
SolrCloud fans a query out to every shard automatically because ZooKeeper tracks which cores make up
a collection. User-managed mode has no such registry, so a distributed query is only possible if
you name every core involved, explicitly, on every request via the shards parameter:
# Query two independently-managed cores as if they were one logical index.
# Each entry is host:port/base_path, comma-separated -- no collection name involved.
curl --get "http://coordinator:8983/solr/books_core/select" \
--data-urlencode 'q=title:darkness' \
--data-urlencode 'shards=solr1:8983/solr/books_core,solr2:8983/solr/books_core'
# shards.info=true reports which shard each result came from and how long it took.
curl --get "http://coordinator:8983/solr/books_core/select" \
--data-urlencode 'q=title:darkness' \
--data-urlencode 'shards=solr1:8983/solr/books_core,solr2:8983/solr/books_core' \
--data-urlencode 'shards.info=true'
# fl=id,[shard] tags each returned document with the shard URL it was fetched from.
curl --get "http://coordinator:8983/solr/books_core/select" \
--data-urlencode 'q=title:darkness' \
--data-urlencode 'shards=solr1:8983/solr/books_core,solr2:8983/solr/books_core' \
--data-urlencode 'fl=id,[shard]'
# https://solr.apache.org/guide/solr/latest/deployment-guide/user-managed-distributed-search.html
The request that receives shards acts as a coordinator for that one call only — it scatters the
query to every listed core, merges the results, and replies; nothing about that role is persistent or
elected, unlike a SolrCloud coordinating node. Because it is only a query-time parameter, it is
tempting to bake it into a request handler’s defaults in solrconfig.xml so clients don’t have to
repeat it — the Reference Guide explicitly warns against adding shards as a default on the
standard /select handler, since a shard receiving its own scattered query can re-scatter it and
loop. From Solr 9 on, any host named in shards must also be allow-listed via allowUrls (or a
configured allow-list mechanism) on the receiving node, a hardening measure against a request being
used to make the server call out to an arbitrary URL.
There is no equivalent of SolrCloud’s automatic routing-by-document-id here: you decide, at index
time, which document goes to which core, and you must repeat that same partition consistently as the
shards list on every query, by hand — exactly the manual version of what
SolrCloud’s distributed indexing & search
does for you automatically once shards and routing are collection-managed. Full parameter reference:
User-Managed
Distributed Search.
When user-managed mode is still the right choice
SolrCloud is the default these pages otherwise assume, and is the right choice whenever you need elastic scaling, automatic failover, or more than a handful of nodes — running a ZooKeeper ensemble is a small, well-documented cost against manually reconfiguring leader/follower roles during an outage. User-managed mode remains reasonable when:
-
A single node is genuinely enough — development, CI, small internal tools — and the operational overhead of ZooKeeper buys nothing.
-
Read replicas without elastic scaling — a fixed, small leader/follower topology (one writer, a known number of read replicas behind a load balancer) is simpler to reason about than a collection you never intend to reshard.
-
An external orchestrator already owns failover — some embedded or appliance-style deployments wire their own health checks and DNS/VIP failover around a leader/follower pair instead of delegating that to Solr.
-
Constrained or air-gapped environments where running and securing a separate ZooKeeper ensemble is disproportionate to a small, largely static index.
Outside those cases, prefer SolrCloud architecture and
Collections & configsets, which give you automatic
sharding, leader election, and failover for the same /select and /update surface described in
Core concepts & architecture. Rolling a
user-managed deployment into production is covered alongside SolrCloud’s in
Deployment & upgrades.