When an ERPNext read replica helps and when it does not
A read replica helps only when the slow load is read-heavy and can tolerate a short delay in the data it shows. Saves, submissions, stock postings and every other write still land on the primary, so a replica does nothing for a slow save. If your General Ledger or stock report locks users out of their own work, the first question is whether the report runs against data that is a few seconds or minutes old without harm. If the answer is no, a replica will not fix the problem, and you should look at the report itself.
The replica is a second MariaDB server with its own storage, backups, patching, monitoring and failover planning. Replication lag becomes a number your team must watch, and reports that depend on the newest postings can show incomplete figures during a period close. Before you route anything, confirm with your own environment how ERPNext and your deployment method handle the replica connection, and test that reports return the figures your controllers expect. Also check that your credentials, network path and backup scope cover the new server, since none of these come for free with a replica.
A replica is a scaling decision, not a fix for a bad query. If the slow report scans a large table without a usable index, or a stock closing entry is missing, the replica only moves the same expensive work to another server and may hide the cause. Profile the query first, then decide. If the primary is short on memory, CPU or disk for the whole workload, vertical scaling and database tuning are often the simpler next step. Choose the replica when read load is clearly the bottleneck, the reports tolerate lag, and your team can run a second database for the life of the system.
Which ERPNext workloads move to the replica and which stay on the primary
Report and list reads are the usual first candidates because they read heavily and write nothing. A General Ledger or stock balance report can scan large tables, and a short delay in the figures rarely changes a decision made from them. The risk is staleness: a user who has just posted an invoice and then opens a list on the replica may not see it yet.
- Candidates: Script reports, query reports and list view counts that only read data.
- Stale data risk: Users may see a document they just saved missing from a list or total, which produces support tickets but no data loss.
- Test: Post a known transaction, then compare report output from the primary and the replica using identical filters.
- Permissions: Confirm that user and role permissions still apply to replica results in the same way.
- Prepared reports: Check which background path builds each prepared report and which database connection it uses.
Before relying on any speedup, confirm which report code paths in your Frappe version actually honor replica routing.
Saves, submits and cancels write to the primary and depend on the current state of the document they change. Frappe reads the record, validates links and computes totals as part of the transaction, so these paths must stay on the primary. Replica lag here can produce validation errors, rejected naming checks or conflicting updates that look random to users.
- Keep on primary: Save, submit and cancel, together with the stock and ledger postings they trigger.
- Stale read risk: Link validation against a lagging replica may reject valid input or allow a conflicting value to pass.
- Form loads: Opening a form is a read, but the version a user edits must be current, so test form loads separately before routing them.
- Lag test: Submit a document, then query the replica immediately and measure how long the change takes to appear.
- Concurrency test: Run parallel saves against the same series and confirm that numbering and totals stay correct.
Before enabling any routing for desk forms, check the database connections recorded during save and submit requests in your logs and confirm that they only reach the primary.
Background work mixes two kinds of jobs. Some produce reports, exports, email digests or aggregations that read large data sets and tolerate a little lag. Others create or update documents, such as recurring invoices, auto repeat entries or stock reposting, and they must see the latest committed state. A job that runs before replication catches up can act on outdated data without raising an error.
- Good candidates: Scheduled report emails, exports and read-only aggregations.
- Keep on primary: Auto repeat, recurring documents, stock reposting and any job that creates or updates records.
- Stale read risk: A job may skip a new record or process an old version of one, and the Scheduled Job Log may show success.
- Test: Write a record, trigger the job immediately, and confirm it sees the change. Compare results with and without routing.
- Queue settings: Confirm whether queue or worker settings affect routing at all in your version, since they may not.
Before moving any scheduled job to the replica, list each job by name and record a routing decision for it.
Data Import and migration scripts write large volumes and often look up records created earlier in the same run. The ERPNext Data Import documentation advises importing only a few thousand records at a time, so imports are slow and run for long periods. A replica that lags behind a stream of writes may not yet contain parent records that later rows reference.
- Keep on primary: Data Import, bulk updates, migration scripts and opening balance loads.
- Stale read risk: Child rows and link fields that reference a parent created moments earlier may fail to resolve.
- Duplicate risk: A retry triggered by a missing lookup can create duplicate records if reads are inconsistent.
- Sample run: Load a representative batch with and without routing, then compare record counts and link errors.
- Cutover step: Document the switch from migration to production reads as a planned step with a verification query.
Before the first production load, confirm that no lookup inside the migration job can fall back to the replica.
Replica configuration options compared with vertical scaling
This table compares four ways to relieve a busy ERPNext database: a larger primary server, a read replica for reports, moving background workers to their own connection, and prepared reports. Read each row against the problem you are seeing, then check the data freshness and operations columns before choosing. In most cases the right answer combines two options rather than picking one.
| Option | What it fixes | Operational cost and data freshness | When it fits |
|---|---|---|---|
| Larger primary server | Raw CPU, memory and disk pressure on every request, including writes and reports | One machine still serves everything; freshness is immediate; hardware changes need a maintenance window | Load is broadly high, the buffer pool no longer fits the working set, and one server is simplest to run |
| Read replica for heavy reports | Long read queries from General Ledger, stock and other reports competing with desk saves | Adds a second MariaDB to patch and monitor, plus replica credentials and lag checks; reports may show slightly older data | Reports are the main load, transactions stay fast on the primary, and users accept reports reflecting recent replication |
| Separate database connection for background workers | Scheduled jobs and long imports slowing interactive users on the same database | Needs worker routing configured and tested; job results still write to the primary, so freshness is unchanged | Queues like long or default are heavy and interactive response times suffer during batch runs |
| Prepared reports | Repeated execution of expensive report queries by the same users | Runs in the background and stores output; no extra server, but results are as old as the last run | Reports are run on a schedule or by many users with the same filters and exact current figures are not needed |
Setting up an ERPNext read replica step by step
This sequence moves heavy report reads off the primary MariaDB database and onto a replica that the site can use for reads. Each step ends with a check you can record, so you know the replica is current, the credentials work and the routing is in effect before you rely on it.
Confirm version and replication support
Before anything is provisioned, record the ERPNext and Frappe Framework version, the MariaDB version on the primary and the replication method your database team plans to use. Confirm in the Frappe documentation for your version that read replica routing is supported and which site_config keys it expects, because key names can differ between releases. Check the supported versions page so you know the version is still receiving fixes. Done when you have a written version matrix signed off by the people who will run the database. Confirm details with your own environment before you build.
Provision the replica from a consistent copy
Your database team creates a replica host with the same MariaDB major version as the primary and seeds it from a consistent snapshot of the site database taken with replication coordinates or GTID position recorded. Keep the site in a known state during the copy, or use a backup that was taken with consistent transaction handling. Done when the replica reports that replication is running with no errors and its position is advancing. Record the start time and the replica's reported lag.
Create a read-only replication account
On the primary, create a dedicated database user for the ERPNext site that has only the grants needed to read the site schema on the replica. Do not reuse the admin or the application's write account. Test the login from the bench host with the mysql client and run a SELECT against a large DocType table such as the General Ledger Entry table, then attempt an INSERT and confirm it is refused. Done when the read login succeeds and the write attempt fails with a permission error.
Set replica host and credentials in site config
Edit the site's site_config.json on the bench to add the replica host, port and read-only credentials using the exact key names from the Frappe documentation for your version. Store the password in the way your organization handles secrets, and restrict file permissions so only the bench user can read it. Do not change the primary connection settings. Done when bench can read the site config and the keys are present with the expected names, verified by a
bench --siteconfig read command.Restart workers and the scheduler
Restart the bench services so the web workers, background workers and scheduler all load the updated site configuration. Confirm that each process restarted cleanly by checking the service status and the logs for connection errors to the replica. Done when all processes report healthy and the logs show successful connections to both the primary and the replica without authentication failures.
Compare a report before and after routing
Pick a heavy report, such as General Ledger, and run it on the primary before routing is active, noting the run time and the row count returned for a fixed filter and date range. After routing, run the same report with the same filters and compare the row count and totals. Check replica lag at the same moment. Done when the totals match and the run time change is recorded. Illustrative example: if lag is several seconds, a report on a fresh ledger may show older numbers than a write made a moment earlier.
Verify writes stay on the primary
Create a test document on the primary, such as a draft Note, and confirm it saves and is visible in the desk. Then check that save and submit actions are not sent to the replica by reviewing the database connection behavior in the logs or with your database monitoring. Reads that need current data, such as a document opened right after saving, should use the primary. Done when the write succeeds, the record appears immediately and the replica eventually shows the same record within your measured lag.
Replication lag and stale data in financial reports
Replication lag means a report run on the replica can omit a posting that was saved on the primary seconds or minutes earlier. An accountant who submits a Sales Invoice and then opens the General Ledger on the replica may see a balance that does not yet include it, which looks like a posting failure even though the data is in transit. Before you route any accounting report to a replica, agree with the finance team what staleness they will accept, and write that tolerance down. Your own tolerance, measured against the replication path in your environment, should decide the rules below, not a default.
Measure lag on the replica itself rather than assuming it is zero. On a MariaDB replica, the replica status output reports the seconds behind the primary, and monitoring should poll it at a short interval and record the maximum over each window. Pair that number with a canary check: insert a known row on the primary, time how long it takes to appear on the replica, and log the result. Keep General Ledger, Trial Balance, Balance Sheet, Profit and Loss, Accounts Receivable and Payable, and any report used for period close or reconciliation on the primary. Stock ledger and stock balance reports that feed valuation should also stay there unless your team has tested them against lag. Reserve the replica for exploratory, read-heavy reports where a slightly older view is acceptable and labeled as such.
Alert when measured lag exceeds the tolerance your finance team set, and when replication stops entirely, since a stopped replica produces stale data without an obvious error in the desk. The alert should name the site and the replica, and it should fire before the threshold is crossed in practice. Design a fallback so that when lag is above tolerance or the replica is unreachable, the affected reports and the read_from_replica path read from the primary automatically. Confirm in your Frappe version how replica routing is enabled and how a fallback is triggered, and test both paths before go-live. Show the reader a visible indicator of which source a report used, so that a figure is never presented as current when it came from a lagging copy.
Replica credentials, network access and data exposure
A replica is a second copy of production data, so it inherits the same personal and financial exposure as the primary. The cards below set out the controls the database team owns, and the checks each one needs before the application starts sending report queries to it.
Read-only replica user
Create a dedicated MariaDB account for report reads and grant only SELECT on the ERPNext site schemas. Do not reuse the site's write account, and do not let the replica user create temporary tables or access other schemas unless a specific report needs them. The database team should confirm the grants with SHOW GRANTS after every change, since a broad grant on one schema is the most common way read paths end up with write access.
Network restriction of the replica port
Limit the replica's MariaDB port to the application servers and the bench workers that run reports, using firewall rules or security groups you control. The network team owns this rule set, and it should be reviewed whenever a new worker host is added. Confirm that the replica is not reachable from user networks or from any public address, even through a load balancer used for other services.
TLS between application and replica
Require encrypted connections from the application to the replica so report data and credentials do not cross the network in clear text. The database team should configure the replica's server certificate, and the platform team should confirm that the client settings in the site configuration use the same trust chain. Test the connection from each worker host, because a host that falls back to an unencrypted session may not show an error.
Personal and financial data on a second server
A replica holds the same ledgers, customer records, employee data and stock history as production, so it falls under the same data protection duties. Confirm with your privacy and finance owners that the replica is in the same approved location, that access is limited to roles already allowed to see the source data, and that its retention matches the primary. Treat the replica as a production data store in your classification and access reviews.
Backups of the replica
Backups taken from the replica are full copies of sensitive data, and they often get less attention than production backups because the replica is seen as disposable. Decide whether the replica needs its own backup at all, since it can usually be rebuilt from the primary. If backups are kept, apply the same encryption, retention and restore access rules as the primary, and record where they are stored.
Credential rotation in site configuration
Replica credentials are stored in the site configuration for each site, so rotation means changing the password in MariaDB, updating the site configuration on every bench, and restarting workers so they pick up the new value. The operations team should write this as a runbook and rehearse it on a non-production site. Confirm that old passwords are revoked only after all workers have restarted, or reports will fail silently during the change.
Logging and audit of replica reads
Enable MariaDB's general or audit logging for the replica user where your policy requires a record of who read which data and when. Confirm the log volume and retention with the database team before enabling it, because full query logs grow quickly on a reporting workload. Store logs outside the replica so an attacker or a faulty report cannot erase the evidence of its own access.
Questions buyers ask before adding an ERPNext read replica
What drives the cost of adding a MariaDB read replica to ERPNext?
The cost is driven by how many people and how much infrastructure the replica needs, not by the replica software itself. The main components are the work to design the topology, the replica server or cloud instance and its storage, the network path between primary and replica, monitoring, and the testing needed to show that reports return correct results. Most of the recurring cost comes from running the replica: patching, capacity changes and keeping replication healthy. Ask any quote to list each component separately, state which items are one-time and which recur, and name the environments it covers, such as staging and production. Because DeployOpen works from a written scope, the quote will follow directly from those lines.
Can our team set up an ERPNext read replica without outside help?
A team with Linux, MariaDB and Frappe bench experience can attempt it, but the risk sits in the details: replication user privileges, consistent starting snapshots, and making sure ERPNext routes only the right reads to the replica. Before deciding, check whether you have someone who can read replication status, test failover paths and roll back a bad configuration on a live site. Also check whether your team can verify that reports against the replica match the primary. If any of these are missing, a fixed-scope engagement can cover the build and handover, so your staff learn the setup while the risky steps are done and checked.
What does the work need from our DBA and platform staff?
Your database and platform staff own the decisions that depend on your environment, and they need to be involved early. The DBA typically reviews replication settings, the backup approach for both servers, privilege grants, and how replica lag will be monitored. The platform team typically owns the server or instance, network rules, TLS between nodes, storage sizing and any load balancer or DNS names. Agree on who approves changes to the primary, because a misconfigured replica can affect production writes. Confirm these responsibilities in the written scope so that each group knows what it must provide and when.
How long does a first ERPNext read replica setup usually take, and what decides it?
The duration depends on the size of the database, how many sites share the server, how many environments need a replica, and how many reports must be checked before cutover. Access approvals and change windows on your side often take as long as the technical steps. Testing against realistic report volumes also adds time, so ask the quote to show the testing phase separately. No duration is given here because none has been supplied for this topic. Confirm the expected timeline against the scope and the schedule your change board can accept.
Does a read replica replace a larger primary database server?
No. A replica moves read traffic away from the primary, so heavy reports stop competing with saves, submissions and background jobs. It does not add write capacity, and every write still lands on the primary. If the primary is short on memory, CPU or disk for its own workload, a larger server or better tuning of the primary is often the correct first step. Before deciding, look at whether slow pages come from writes, from reports, or from background queues, and whether the database buffer pool is sized to the working set. A replica helps when reads are the bottleneck and the primary has headroom for its writes.
Which ERPNext reads can safely go to a replica, and which must stay on the primary?
Reports and list views that only read data are the usual candidates, but routing must be checked report by report. Reads that feed a save, a submit, a stock posting or a scheduled job that writes data must stay on the primary, because replicas lag behind the primary and can return slightly older data. Engineers should test each routed report for freshness requirements, confirm which configuration keys control routing in the installed version, and document the list. Ask any engagement to deliver that list as part of its scope, together with the test results for each report.
What ongoing work follows after the replica goes live?
Once live, the replica needs monitoring for replication lag and errors, regular backups or the ability to rebuild it from the primary, patching of MariaDB on both servers, and reviews after major ERPNext upgrades. Someone must also watch for new reports that should or should not use the replica, and for changes in report volume that affect sizing. Ask the quote to state whether these tasks are included in the build, handed to your team with a runbook, or covered by an ongoing support retainer. Ongoing support and upgrades are available as retainers, and the scope should show which tasks fall into that arrangement.
How DeployOpen works on this
DeployOpen plans, builds and documents a MariaDB read replica for ERPNext inside your own infrastructure, starting from a written scope. The work covers which reports move to the replica, the credentials and site configuration involved, verification that reads land where intended, and the runbook your team keeps after handover.
How we scope
- Inventory the heavy reports and pages that your users run most, with timings captured from your own sites
- Confirm your ERPNext and Frappe version, deployment method and whether the database runs on VMs, bare metal or Kubernetes
- Agree in writing which sites, replica hosts, credentials and monitoring items are in scope before work starts
- Record who approves the change, who owns the replica afterward and which reports must always read from the primary
How we build
- Create replica credentials with read-only grants and configure the replication user under your security policy
- Set the replica connection keys in site configuration for each site in scope, one site at a time
- Test that routed reports return the same figures as the primary, including reports that depend on recent postings
- Check replication lag, failover behavior and connection handling under your expected report load before go-live
How we hand over
- Deliver a written runbook covering routing rules, configuration keys, credential rotation and rollback steps
- Document which features read from the replica and which always write or read the primary
- Walk your platform and DBA teams through lag alerts, replica restarts and how to disable routing quickly
- Provide a change record listing each site, configuration value and test result for your audit trail
How we support
- Ongoing support, upgrades and continuous testing are available as retainers, scoped separately from the build
- Re-test routing after each ERPNext or Frappe upgrade, since report code and database access can change between releases
- Review replica lag and report timings with your team on the cadence agreed in the retainer
- Confirm with us in the scope whether vertical scaling of the primary should be evaluated before or alongside the replica

