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.