On this page

The Medplum API uses a number of safeguards against bursts of incoming traffic to help maximize its stability. Users who send many requests in quick succession may receive HTTP error responses with status code `429 Too Many Requests`.

## Total Requests Rate Limit  
| Category | Free tier | Paid tier |
| --- | --- | --- |
| Login (`/auth/login`, `/auth/newuser`, `/auth/newproject`) | 5 requests per IP per minute | 5 requests per IP per minute |
| Auth (other `/auth/*` and `/oauth2/*` endpoints) | 160 requests per IP per minute | 160 requests per IP per minute |
| Default (all other endpoints, including `/auth/me`) | 6,000 requests per IP per minute | 60,000 requests per IP per minute |

All rate limits are calculated per IP address over a one minute window.

Rate limits can be increased for paid plans. Please [contact us](mailto:info+rate-limits@medplum.com?subject=Increase%20rate%20limits) for more information.

## FHIR Interaction Load Rate Limit  
In addition to limits on the number of requests that can be made to the Medplum server, there is a limit on the total load of the interactions made to the Medplum server. Different interactions with the datastore are weighted by complexity and impact, and **the sum of a user's interactions in a given minute** must remain under the user's total load limit.

The quota is calculated as the sum of each user's interactions in a given minute, where each interaction is weighted by its impact on the data store. Here are the weights used to calculate the quota:

| FHIR Operation | Points Cost | Description |
| --- | --- | --- |
| Read | 1 point | Basic resource read operation |
| Create | 100 points | Creating a new resource |
| Update | 100 points | Full resource update |
| Delete | 100 points | Deleting a resource |
| Patch | 100 points | Partial resource update |
| Search | 20 points | Searching resources |
| History | 10 points | Retrieving resource version history |

Points are counted per logical operation. A single API request can trigger multiple operations (for example, a batch request or a read that resolves many references). In that case, the cost is the sum of each operation's cost.

**Example:** A single batch request that performs 5 resource reads and 1 search consumes 5 × 1 + 1 × 20 = **25 points** (5 for the reads, 20 for the search).

FHIR uses [specific terminology](http://hl7.org/fhir/restful-interaction) to categorize different interactions with the data store, e.g. `search` and `update`. These interactions are weighted by complexity and impact to the data store, with the sum of each user's interactions in a given minute compared to the configured limit. There is also a limit on the total interactions for all users within a Project as a whole, which defaults to ten times the per-user limit.

### How to view and configure FHIR quota rate limits  
You can configure rate limits at the **Server**, **Project**, and **User** levels.

- **Server Level Defaults (Self-Hosting)**: Defined in [Server Configuration](/content/docs/self-hosting/server-config/index.html) using `defaultRateLimit` and `defaultFhirQuota`.
- **Project Level Overrides**: Configured in the `Project.systemSettings` (see below).
- **User Level Overrides**: Configured in `UserConfiguration` resources (see [User Configuration](/content/docs/access/user-configuration#user-specific-fhir-quota-rate-limits/index.html)).

Hosted Medplum

On the hosted Medplum service, **Server-level** and **Project-level** rate limits cannot be set by project administrators. If you would like to discuss or adjust your project's rate limits, please reach out to [support@medplum.com](mailto:support@medplum.com). Project admins can still configure **User-level** overrides via `UserConfiguration` (see [below](/content/docs/rate-limits#setting-a-user-specific-quota-via-projectmembership/index.html)).

To view or update the Project-level limits:

1. Navigate to your list of [Projects](https://app.medplum.com/Project), and find the project.
2. View (or edit, if self-hosting) the `systemSettings` field on the Project resource:

- `userFhirQuota`: Overrides the per-user FHIR interaction limit.
- `totalFhirQuota`: Sets a limit for the _sum_ of all users in the project.

If those values are not set, the server defaults will be used.

To monitor live FHIR quota usage, use the **Rate Limits** dashboard in Medplum App (at [/admin/rate-limits](https://app.medplum.com/admin/rate-limits)) or the [Project `$rate-limits`](/content/docs/api/fhir/operations/project-rate-limits/index.html) operation.

info

There are some scenarios where you may want to **set a custom quota for a User, Bot, or ClientApplication**. For example, say you expect higher traffic for a specific User, Bot, or ClientApplication than the default user quota in your project, you can set a custom quota for that User, Bot, or ClientApplication. See [how to set user-specific FHIR quotas](/content/docs/access/user-configuration#user-specific-fhir-quota-rate-limits/index.html) for more information about how to do this.

**Important:** The `totalFhirQuota` will still be enforced, but `userFhirQuota` will be overridden for the User, Bot, or ClientApplication.

#### Setting a User-specific quota via ProjectMembership  
To apply a custom quota to a specific User, Bot, or ClientApplication, you create a `UserConfiguration` resource with the desired quota and reference it from that member's `ProjectMembership` resource. Project administrators can do this on both hosted and self-hosted Medplum.

1. **Create a `UserConfiguration` resource** with the desired FHIR quota. Set the `fhirQuota` option to the per-minute point limit for this member:

```ts
{

"resourceType": "UserConfiguration",

"name": "High-Traffic Bot Configuration",

"option": [
\
       {\
\
         "id": "fhirQuota",\
\
         "valueInteger": 60000\
\
       }\
\
     ]
}
```

Note the `id` of the created resource — you'll reference it in the next step.

2. **Find the `ProjectMembership`** for the User, Bot, or ClientApplication you want to update. In the Medplum App, go to the **Project Admin** page and select the member, or search for the `ProjectMembership` resource directly.

3. **Set the `userConfiguration` field** on the `ProjectMembership` to reference the `UserConfiguration` created in step 1:

```ts
{

"resourceType": "ProjectMembership",

"userConfiguration": {
       "reference": "UserConfiguration/<your-user-configuration-id>",
       "display": "High-Traffic Bot Configuration"
     },

//...
}
```

4. **Save the `ProjectMembership`.** The custom quota takes effect immediately on subsequent requests made by that member.

See [User Configuration](/content/docs/access/user-configuration#user-specific-fhir-quota-rate-limits/index.html) for more details on the `UserConfiguration` resource.

### Avoiding quota with async batch requests  
[Asynchronous batch requests](/content/docs/fhir-datastore/processing-async-bundles/index.html) do not count the **operations inside the background job** against a user's FHIR interaction quota. If you're running large data seeding or import jobs and hitting quota limits, processing the bundle with the `Prefer: respond-async` header is an alternative to raising the quota. Note that data will not be immediately available until the job completes.

Status polling and reading the result `Binary` still consume quota like ordinary FHIR reads. Plan poll backoff accordingly; see [Processing Asynchronous Bundles](/content/docs/fhir-datastore/processing-async-bundles#rate-limits-and-quotas/index.html) for details.

## Reporting Request and Load Rate Limits: HTTP Headers  
All API calls affected by rate limits will include a `RateLimit` header with details about the applicable limits:

```text
RateLimit: "requests";r=59999;t=60, "fhirInteractions";r=49894;t=60
```

Each logical limit reports the number of units remaining (`r`) and the time remaining, in seconds, until the limit resets (`t`). Applications should use these reported values to proactively slow down activity when few units are remaining, in order to prevent service disruption. Once a `429 Too Many Requests` error is produced, applications should not retry until after at least the indicated number of seconds have passed and the limit has been reset.

- [Total Requests Rate Limit](/content/docs/rate-limits#total-requests-rate-limit/index.html)
- [FHIR Interaction Load Rate Limit](/content/docs/rate-limits#fhir-interaction-load-rate-limit/index.html)
  - [How to view and configure FHIR quota rate limits](/content/docs/rate-limits#how-to-view-and-configure-fhir-quota-rate-limits/index.html)
  - [Avoiding quota with async batch requests](/content/docs/rate-limits#avoiding-quota-with-async-batch-requests/index.html)
- [Reporting Request and Load Rate Limits: HTTP Headers](/content/docs/rate-limits#reporting-request-and-load-rate-limits-http-headers/index.html)
