Why one runaway integration can slow ERPNext for every user
ERPNext API rate limiting caps how many requests a client can make in a set time window, so one integration cannot starve every other user of the same site. The scenario that makes this concrete is common: a finance or operations lead ships a bad deploy to a sync job or storefront connector, the job retries in a tight loop, and the ERPNext API receives thousands of requests in minutes. Desk users then see slow saves, stalled reports and login delays, even though nobody changed the ERPNext configuration. A limit on the integration's requests is the control that keeps that one client from consuming the capacity everyone else shares.
Teams usually need this control when several systems write to the same site, when a storefront or marketplace connector calls the API on every order change, or when a scheduled job pulls large record sets at fixed times. It matters most on shared sites where sales, stock and accounting users work in the same database. Before you configure anything, list every API client, its key or user, its expected request pattern and the business owner who can pause it. Confirm in the Frappe documentation for your version how the rate limit is enabled and scoped, because the exact settings and where they apply are version-specific.
Rate limiting is only a partial answer. If the slow behavior comes from an expensive query, a report that scans large General Ledger or stock tables, or a missing index, a lower request count will reduce pressure but will not fix the query. Each request still costs the database the same amount of work. Check whether the spike is high request volume or long individual requests before choosing a limit. Your own logs and the Frappe Framework documentation should confirm which of the two you are seeing.
How Frappe's time-based fixed-window limit counts requests
A fixed window counts requests inside one fixed period of time. Every request that arrives during the period increments a counter, and when the period ends the counter resets to zero and a new period begins. Until the limit is reached, requests are accepted; after it is reached, further requests in that same period are refused with HTTP 429 until the window rolls over. The consequence for planning is that the limit is a ceiling per period, not a smooth rate. An integration that sends its full allowance at the end of one window and again at the start of the next can push roughly twice the nominal rate through the boundary in a short span. Treat the configured number as the maximum a single window will admit, and size your database, workers and upstream systems for the burst that a boundary can produce, not only for the average.
The counter is keyed to the request source as Frappe identifies it, so the practical question for an operator is which identity Frappe uses for an API caller: a user, an API key, or the client address seen by the application. That choice decides whether one runaway integration is isolated or whether several integrations behind one proxy or NAT share a single budget. Confirm this in the Frappe source for your exact version, including the name of the key it builds, the time window it uses and where the counter is stored, whether in Redis through the cache layer or somewhere else. Storage location matters: a counter held in a shared cache behaves differently across multiple web workers and after a cache flush than a per-process counter would. Ask your implementation team to document these answers for your deployment and to test them with two concurrent callers before relying on the limit.
Choosing limit and window values for each integration
This table compares the main decisions you face when setting ERPNext API rate limits, from a site-wide ceiling to exceptions for trusted services. Read each row as a question to answer for every integration, then check the trade-off before changing a value. Exact configuration keys and accepted values must be confirmed in your installed Frappe version and on a test site first.
| Decision | What it controls | When it fits | Main trade-off |
|---|---|---|---|
| Site-wide ceiling | Maximum API requests one user or client can make to the site within each window | Protects the site from a single runaway script or misconfigured client that would otherwise affect every user | Set too low, legitimate peaks such as month-end exports get throttled and users see 429 responses |
| Separate bulk sync budget | A distinct, usually higher or longer-window allowance for scheduled bulk jobs | Nightly or hourly syncs from a marketplace, bank feed or warehouse system that move many records in one run | Needs a dedicated API user so bulk traffic can be told apart from interactive traffic |
| Interactive user allowance | The request budget for desk and portal users acting by hand | Staff clicking through forms, reports and list views during the working day | Tight limits here feel like a site fault to users, so changes need communication |
| Short window for bursts | Counts requests over a few seconds or minutes to catch sudden spikes | Stops a loop or retry storm that fires hundreds of calls at once | Short windows reject legitimate bursts, such as a batch of parallel lookups from a single job |
| Longer window for smoothing | Counts requests over an hour or a day to cap total volume | Keeps sustained high volume in check while allowing short peaks | A long window can let a runaway client use its full quota in one burst before the reset |
| Excluded or raised limit for trusted services | Removes or raises the limit for named internal service accounts | Internal services already governed by your own change control and monitoring | Exclusions remove a safety net, so pair them with alerting and a named owner |
| Per-integration review | Records the chosen values, owner and expected volume for each API user | Any integration that writes data or runs on a schedule | Values drift over time unless reviewed after upgrades and volume changes |
| Verification on a test site | Confirms the keys, accepted values and fixed-window behavior in your installed version | Before any value reaches production | Requires a load test that mirrors real job timing, which takes planning effort |
Which limit profile fits each type of integration
A scheduled bulk sync usually runs on a timer, such as a nightly job that pushes item masters, customers or stock counts from an external system into ERPNext. Its traffic is predictable but dense: many requests arrive within a short window, then the client goes quiet until the next run. The main risk when unlimited is that a sync that overruns its window keeps competing with interactive users for workers and database connections, and a bug that re-queues records can turn one run into a loop.
- Run window: Ask the integration owner when the job starts, how long a full run takes today, and whether it must finish before business hours.
- Batch and page size: Confirm how many records each request carries and whether the client paginates with a fixed page size.
- Retry behavior: Find out whether failed batches retry immediately, with backoff, or restart the whole run.
- Logs to watch: Count requests per minute by user or API key, and look for HTTP 429 responses clustering at the same clock time each night.
Before you raise any limit for a bulk job, confirm that the job itself is idempotent, because a higher ceiling only helps if repeated requests do not duplicate records.
Ecommerce and marketplace connectors push orders as customers buy, so their traffic follows promotions, marketplace feeds and time zones rather than a schedule. Volume can be quiet for hours and then spike when a campaign starts or when a marketplace retries a batch of notifications it could not deliver. The risk when unlimited is that a spike of order creation saturates the ERPNext workers used for document saves and submissions, slowing the desk for warehouse and finance staff at the same moment.
- Peak profile: Ask for the expected peak orders per minute, the source of that number, and any planned sales events that change it.
- Retry and redelivery: Confirm whether the marketplace redelivers webhooks or orders after a timeout, and how long it waits between attempts.
- Idempotency keys: Check that the connector recognizes an order it has already created, so a retry does not produce a second Sales Order.
- Logs to watch: Track 429 and 5xx responses on order endpoints, and compare the order rate in the connector log with the Error Log in ERPNext.
Ask the connector vendor to state whether it backs off on HTTP 429 responses. A connector that retries immediately can multiply the load that the limit was meant to contain.
Reporting and BI tools pull large result sets, often by paging through a list endpoint or requesting a full table for a dashboard refresh. Their requests are fewer than sync jobs but each one is heavy, and dashboards may refresh on many users' schedules at once. The risk when unlimited is that a single analytics refresh reads a large portion of a DocType and holds database resources that the desk needs, so the problem appears as slow pages rather than as obvious API errors.
- Refresh schedule: Ask how often each dashboard refreshes, how many users share one service account, and whether refreshes are triggered manually.
- Result size: Confirm the page size and fields requested, and whether the tool can request only the columns it charts.
- Preferred path: Ask whether the integration can use a prepared report or a read replica instead of the live API, if your deployment has one.
- Logs to watch: Look at response times and row counts for the service account, and correlate slow desk pages with BI refresh times.
A rate limit alone will not fix a heavy query. Pair the limit with narrower field selection and a schedule that keeps refreshes away from month-end close.
Staff-facing mobile apps and custom in-house tools make interactive calls, such as looking up a stock item, recording a pick or checking a customer balance. Traffic is bursty but human-paced, and it comes from a relatively small, known user group. The risk when limits are set too tightly is that warehouse or field staff see errors during normal work, while a limit set too loosely lets a buggy screen that polls in a tight loop flood the API. Both failures tend to surface as complaints rather than as clean alerts.
- User count: Ask how many devices or users will call the API at the busiest shift and whether they share credentials.
- Polling behavior: Confirm whether the app polls on a timer, refreshes on each screen load, or uses events, and what the minimum interval is.
- Offline handling: Check how the app queues actions when the network drops and whether it resends them in bursts on reconnect.
- Logs to watch: Group requests by user and device, and alert on any single client sending requests at a rate no person could produce.
Give each app its own API key or user so that a limit violation points to one client. Shared credentials make the logs useless for diagnosing which screen caused the spike.
Setting up rate limits on a test site before production
This sequence moves an ERPNext API rate limit from assumption to measured setting. It starts with knowing every client, proves the limit on a non-production site, and then rolls it out one client at a time with monitoring in place.
Inventory every API client and its traffic pattern
List each integration, script, mobile app, reporting tool and scheduled job that calls the ERPNext API, along with the user or API key it authenticates as. For each one, record how often it calls, which endpoints it hits, whether it runs in bursts or steadily, and which business process depends on it. Confirm that the list includes desk users and background jobs, since the goal is to protect interactive work from machine traffic. The step is done when the owner of each client has signed off on its pattern.
Reproduce peak load on a non-production site
Build a test site on the same ERPNext and Frappe version as production, with comparable data volume and the same proxy and worker layout where possible. Replay the traffic patterns from the inventory using a load tool, including the worst realistic burst for each client, and include a set of desk sessions performing normal saves and list views at the same time. The check is that the test site reproduces the slow responses or errors you already see in production, so the test results can be trusted before you change anything.
Set initial values and record a baseline
Before enabling any limit, run the replayed load with no rate limit configured and record response times, error rates, worker queue depth and database load for each client and for the desk. Choose starting limit and window values from this baseline and document the reasoning for each client, including the expected peak. Store the configuration and the baseline results together so they can be compared later. The step is complete when the baseline and the proposed values are written down and reviewed by the team that owns the integration.
Enable the limit and confirm the 429 behavior
Turn on the rate limit on the test site and deliberately overload one client above its window. Confirm that the API returns HTTP 429 responses for the overloaded client, that the response headers show the limit information your clients will read, and that the desk stays responsive during the test. Then run a test client that honors 429 responses and confirm it backs off instead of retrying in a tight loop. The step is done when the rejections are predictable and the test client behaves as the integration owner expects.
Verify that desk users are not affected
While the integration load runs against the test site, have a group of users perform everyday desk work such as creating sales invoices, opening stock reports and saving documents. Confirm that the limit applies only to the API clients you intended and that interactive pages keep their normal response times. If desk requests are being limited or slowed, adjust the scope of the limit before moving on. The step is complete when desk work continues normally under full API load.
Confirm rejections appear in logs and alerts
Check that every rejected request is visible in the places your operations team will watch, including the server access logs and any monitoring you have configured for 4xx and 5xx responses. Create a test alert on the rejection rate for each client and confirm it fires during the deliberate overload. Verify that the log entries contain enough information to identify the client, endpoint and time. The step is done when a rejection from any client can be traced to its source within your normal monitoring workflow.
Roll out per client with monitoring
Enable the limit in production one client at a time, starting with the client that has the most predictable traffic, and watch the baseline metrics after each change. Keep the previous configuration ready so you can revert quickly, and tell each integration owner which headers and 429 behavior to expect. Repeat the comparison against the recorded baseline and adjust values only where the data shows a clear need. The rollout is complete when every client is limited, the desk metrics match the baseline, and each owner confirms their integration handles rejections correctly.
Handling HTTP 429 responses in integrations and clients
When an ERPNext site returns HTTP 429, the integration should stop sending requests to that site immediately, not retry in a tight loop. Read any retry guidance in the response first, then wait before resuming. If no guidance is present, back off exponentially with jitter so that many parallel workers do not all come back at the same moment. Resume only at a pace that stays inside the configured limit, and cap the total number of retries so a stuck job fails visibly and lands in the client's error queue instead of hammering the site indefinitely.
Retries are safe only for requests that cannot create duplicates. A timed-out or 429-rejected POST to create a Sales Invoice or Stock Entry may or may not have been processed, so a blind retry can book the same sale or stock movement twice. Clients should send a stable external reference with each write, check for an existing record with that reference before re-posting, and treat every create as conditional on that check. Use the same logic for updates and for Stock Entry submissions, where a duplicate movement is hard to unwind cleanly.
Before any client depends on specific headers, such as a remaining-quota counter or a reset time, the owning team must confirm the exact response headers that the installed ERPNext and Frappe version returns for a 429. Test this against the real site with a deliberate burst of requests, and record the results in the integration's runbook. The client owner, usually the team that built the integration rather than DeployOpen, normally holds the retry, backoff and idempotency logic, so that team should own these tests and the decision on what to do when the limit is hit.
Security and operations risks in API rate limiting
A rate limit only protects ERPNext if it stops the right traffic without blocking the work the business depends on. The cards below cover the failure modes we see most often when limits are added to a running site, and the control to put in place for each one.
Limits evaded by rotating credentials
A limit keyed to an API key or user is weak if one integration can create or borrow several keys, or spread requests across many user accounts. A runaway script can then keep going while each individual key looks within bounds. Review which users can generate API keys, restrict key creation to named service accounts, and count traffic per integration in your logs so that a spread of keys still shows up as one source of load.
Limits that block month-end work
A limit tuned for normal browsing can stop a legitimate bulk job, such as a nightly sync, a data import or a month-end reconciliation pulled through the API. The failure shows up as a sudden run of 429 responses at the worst moment. Before you set values, list the scheduled and batch jobs that call the API, measure their peak request rate in a test environment, and agree on an exception path for named service accounts.
Unmonitored 429 volume
Rejected requests are easy to miss because the integration usually retries and the desk keeps working. Without monitoring, a limit that is too low can quietly delay sales orders or stock updates for days. Log every 429 with the user, endpoint and client address, chart the volume per hour, and alert when one integration crosses a threshold you set during testing. Treat a sustained spike as an incident, not as the limit working.
Secrets kept apart from limit settings
Limit configuration and API credentials should be managed as separate concerns. If keys live in the same site configuration file or change record as the limit values, a change review can expose secrets, and a rotation can accidentally reset a limit. Store API secrets in your approved secrets manager, keep limit values in version-controlled configuration, and give each team its own change path for each.
Reverse proxy hides the client address
When Nginx or a load balancer sits in front of Frappe, every request can arrive from the proxy's address. A limit keyed on client address then treats all users as one client, which either blocks everyone or protects nothing. Confirm which headers your proxy sets, restrict which hops Frappe trusts to set the forwarded address, and test with two clients to confirm each one is counted separately before you rely on address-based limits.
Uncontrolled changes to limit values
Limit values are operational settings with security effects, yet they are often changed by hand on a live site during an incident. Record every change with its reason, the previous value and the approver, and test each new value in staging against the known batch jobs before it reaches production. Review the values on a fixed schedule, so that limits set for a past integration do not remain in place after that integration is retired.
What to confirm in your environment before relying on the limit
Before you rely on a rate limit for ERPNext, confirm the exact configuration keys for your Frappe version and where they are set. Check whether the values live in the site's site_config.json, in the bench-level configuration, or in a deployment override such as the environment files used by the frappe_docker setup, and confirm which of these wins when they disagree. Record the key names, the default behavior when a key is absent, and whether a change needs a bench restart or a site-level reload. Do not assume the names used in this page apply unchanged to your release until you have read them in the version you run.
Next, identify the cache backend that holds the rate limit counters and whether every worker and web process reads the same store. A counter kept in a per-process cache will undercount when several gunicorn workers or several servers handle the same integration, so the effective limit can be far looser than the number you configured. Ask how the limit behaves across multiple benches and sites, whether the counter is keyed per user, per API key or per site, and whether two sites on one server share a counter. Also confirm whether background jobs, scheduler runs and webhook deliveries count toward the limit, because an integration that queues work may bypass the window entirely or trip it in bursts.
Finally, test the behavior after upgrades and check how the limit interacts with any API gateway you already operate. A gateway in front of ERPNext may enforce its own limits, rewrite the 429 responses or strip the rate limit headers, so the client sees a different contract than the Frappe application produces. Plan a regression test for each Frappe upgrade that confirms the key names, the window reset behavior and the response headers still match your integration's retry logic. Treat any behavior you have not observed in your own environment as unconfirmed until a test or the vendor documentation for your version shows it.
Questions buyers ask before setting ERPNext API limits
How much effort does configuring and testing ERPNext API limits take?
Effort depends mainly on how many integrations call the API, how their traffic is shaped, and how many environments need matching limits. A single well-understood integration with predictable batch jobs is a small, bounded task. A landscape of marketplace connectors, reporting tools, mobile clients and custom scripts takes longer because each caller needs its own measured profile before a number is chosen. Ask any provider to break the estimate down by integration, environment and test cycle, so you can see which items drive the total.
Can our own team set ERPNext API limits without a partner?
Yes, if you have someone who can read Frappe's rate limit settings, interpret access and error logs, and change site configuration under change control. The harder part is usually not the setting itself but knowing what each client should be allowed to do. Teams that already run ERPNext in production and maintain their integrations tend to manage this well. Teams without an integration inventory or a staging site that mirrors production often benefit from outside help for the discovery and testing stages.
What does our team need to provide for this work?
Plan to provide four things: an inventory of every system that calls the ERPNext API, including scheduled jobs and manual scripts; a named owner for each client who can say what volume is normal and what is urgent; a test site where limits can be tried without affecting users; and access to the web server, application and Error Log so that throttled and failed requests can be traced. Without the owners, limits are guesses. Without a test site, the first measurement happens in production.
Can an API gateway replace Frappe's built-in rate limit?
A gateway in front of ERPNext can enforce limits per client, path or key, and it can absorb traffic before it reaches Frappe. It does not automatically give you the same per-user view that Frappe applies inside the application, so the two layers answer different questions. Many teams use both: the gateway for coarse protection and client identification, and Frappe's limit for application-level control. Confirm how your gateway identifies callers, because limits applied to a shared proxy address can throttle the wrong clients.
How long does rollout take, and what drives that duration?
Duration is driven by the number of clients to profile, how many environments must be promoted in order, and how long it takes to observe real traffic through a full business cycle such as month-end or a nightly batch. Coordination with integration owners often takes longer than the configuration itself. Ask for a timeline that separates inventory, staging tests, production change windows and the observation period, since the observation period is the step most often shortened under pressure.
What should a quote for ERPNext API rate limiting include?
A written quote should state the scope in concrete terms: the integrations and environments covered, the limit and window values to be tested, the HTTP 429 handling expected from each client, the header and log checks, and the handover documentation. It should separate one-time work such as discovery and configuration from any recurring review, and it should say what the client must supply. Ask whether testing is included, how changes after go-live are handled, and what happens if a client's traffic pattern changes.
Do limits affect our compliance or security posture?
Rate limits support availability and reduce the chance that one runaway integration degrades financial or inventory processing, which matters for change control and operational controls. They are not a control that auditors will accept on their own, and DeployOpen does not issue audit reports or certifications. Document the limits, the owners, the review cadence and the evidence of testing, then confirm with your auditor which of these artifacts they expect.
How DeployOpen scopes and delivers ERPNext API rate limiting
DeployOpen approaches API rate limiting for ERPNext as a bounded piece of work inside your own infrastructure. We agree the scope in writing, build and test the limits against your real integration traffic, and hand over the settings, runbooks and documentation your team needs to operate them.
How we scope
- Inventory every integration, token holder and scheduled caller that reaches the ERPNext API today.
- Agree which endpoints, users and sites need limits, and which must stay unthrottled.
- Record the agreed limit and window values, 429 handling expectations and sign-off owners in the written scope.
How we build
- Configure the rate limit settings for each site and test them against representative integration load.
- Verify client retry behavior on HTTP 429 responses and confirm the response headers clients rely on.
- Test that legitimate bulk jobs, such as data imports, are paced or scheduled without tripping limits.
How we hand over
- Deliver the final configuration, a change log and a test record covering each agreed endpoint group.
- Document how to choose new limit and window values when a new integration goes live.
- Walk your platform and integration teams through troubleshooting steps for throttled clients and runaway callers.
How we support
- Engagements are fixed-scope, with deliverables and timelines agreed in writing before work starts.
- Ongoing support, upgrades and continuous testing are available as a retainer for changes to limits after go-live.
- Ask any provider to confirm the rate limit behavior of your ERPNext version before committing to a design.

