Skip to content

Commit f45a11d

Browse files
Closes #20382: Document performance best practices (#20384)
1 parent 56db60f commit f45a11d

File tree

3 files changed

+169
-0
lines changed

3 files changed

+169
-0
lines changed

.github/ISSUE_TEMPLATE/03-documentation_change.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,12 @@ body:
2525
- Getting started
2626
- Configuration
2727
- Customization
28+
- Best practices
2829
- Integrations/API
2930
- Plugins
3031
- Administration
32+
- Data model
33+
- Reference
3134
- Development
3235
- Other
3336
validations:
Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
# Performance Handbook
2+
3+
The purpose of this handbook is to help users and administrators use NetBox efficiently. It contains assorted recommendations and best practices compiled over time, intending to serve a wide variety of use cases.
4+
5+
## Server Configuration
6+
7+
### WSGI Server Configuration
8+
9+
NetBox operates as a [Web Server Gateway Interface (WSGI)](https://en.wikipedia.org/wiki/Web_Server_Gateway_Interface) application, which sits behind a frontend HTTP server such as nginx or Apache. The HTTP server handles low-level HTTP request processing and serving static assets, and forwards application-level requests to NetBox via WSGI.
10+
11+
A backend WSGI server (typically [Gunicorn](https://gunicorn.org/) or [uWSGI](https://uwsgi-docs.readthedocs.io/en/latest/)) is responsible for running the NetBox application. This is accomplished by initializing a number of WSGI worker processes which accept WSGI requests relayed from the frontend HTTP server.
12+
13+
Tuning your WSGI server is crucial to realizing optimal performance from NetBox. Below are some recommended configuration parameters.
14+
15+
#### Provision Multiple Workers
16+
17+
General guidance is to set the number of worker processes to double the number of CPU cores available, plus one (`2 * CPUs + 1`).
18+
19+
#### Limit the Worker Lifetime
20+
21+
Set a maximum number of requests that a worker can service before being respawned. This helps protect against potential memory leaks.
22+
23+
#### Set a Request Timeout
24+
25+
Limit the time a worker may spend processing any request. This prevents a long-running request from tying up a worker beyond an acceptable threshold. We suggest a limit of 120 seconds as a reasonable safeguard.
26+
27+
#### Bind Using a Unix Socket
28+
29+
When running the HTTP frontend and WSGI server on the same machine, binding via a Unix socket (instead of a TCP socket) may yield slight performance gains.
30+
31+
### NetBox Configuration
32+
33+
NetBox ships with a reasonable default configuration for most environments, but administrators are encouraged to explore all the [available parameters](../configuration/index.md) to tune their installation. Some of the most notable parameters impacting performance are called out below.
34+
35+
#### Reduce the Maximum Page Size
36+
37+
NetBox paginates large result sets to reduce the overall response size. The [`MAX_PAGE_SIZE`](../configuration/miscellaneous.md#max_page_size) parameter specifies the maximum number of results per page that a client can request. This is set to 1,000 by default. Consider lowering this number if you find that API clients are frequently requesting very large result sets.
38+
39+
#### Limit GraphQL Aliases
40+
41+
By default, NetBox restricts a GraphQL query to 10 aliases. Consider reducing this number by setting [`GRAPHQL_MAX_ALIASES`](../configuration/graphql-api.md#graphql_max_aliases) to a lower value.
42+
43+
#### Designate Isolated Deployments
44+
45+
If your NetBox installation does not have Internet access, set [`ISOLATED_DEPLOYMENT`](../configuration/system.md#isolated_deployment) to True. This will prevent the application from attempting routine external requests.
46+
47+
#### Reduce Sentry Sampling
48+
49+
If [Sentry](https://sentry.io/) has been enabled for error reporting and analytics, consider lowering its sampling rate. This can be accomplished by modifying the values for `sample_rate` and `traces_sample_rate` under [`SENTRY_CONFIG`](../configuration/error-reporting.md#sentry_config).
50+
51+
#### Remove Unneeded Event Handlers
52+
53+
Check whether any custom event handlers have been added under [`EVENTS_PIPELINE`](../configuration/miscellaneous.md#events_pipeline). Remove any that are no longer needed.
54+
55+
### Background Task Workers
56+
57+
NetBox defers the execution of certain tasks to background workers via Redis queues serviced by one or more background workers. These workers operate asynchronously from the frontend WSGI workers, and process tasks in the order they are enqueued.
58+
59+
NetBox creates three default queues for background tasks: `high`, `default`, and `low`. Additional queues can be configured via the [`QUEUE_MAPPINGS`](../configuration/miscellaneous.md#queue_mappings) configuration parameter.
60+
61+
By default, a background worker (spawned via `manage.py rqworker`) will listen to all available queues. To improve responsiveness to high-priority background tasks, consider dedicating one or more workers to service the `high` queue only:
62+
63+
```
64+
$ ./manage.py rqworker high
65+
19:31:20 Worker 861be45b32214afc95c235beeb19c9fa: started with PID 2300029, version 2.6.0
66+
19:31:20 Worker 861be45b32214afc95c235beeb19c9fa: subscribing to channel rq:pubsub:861be45b32214afc95c235beeb19c9fa
67+
19:31:20 *** Listening on high...
68+
19:31:20 Worker 861be45b32214afc95c235beeb19c9fa: cleaning registries for queue: high
69+
19:31:20 Scheduler for high started with PID 2300096
70+
```
71+
72+
## API Clients
73+
74+
### REST API
75+
76+
NetBox's [REST API](../integrations/rest-api.md) is the primary means of integration with external systems, allowing full create, read, update, and delete (CRUD) operations. There are a few performance considerations to keep in mind when dealing with very large data sets.
77+
78+
#### Use "Brief" Mode for Simple Lists
79+
80+
In cases where you need to retrieve only a minimal representation of objects, append `?brief=True` to the URL. This instructs NetBox to omit all fields except the following:
81+
82+
* ID
83+
* URL
84+
* Display text
85+
* Name (or similar identifier)
86+
* Slug (if present)
87+
* Description
88+
* Counts of notable related objects (where applicable)
89+
90+
For example, a site fetched using brief mode returns only the following:
91+
92+
```json
93+
{
94+
"id": 2,
95+
"url": "https://netbox/api/dcim/sites/2/",
96+
"display": "DM-Akron",
97+
"name": "DM-Akron",
98+
"slug": "dm-akron",
99+
"description": ""
100+
}
101+
```
102+
103+
Omitting all other fields (especially those which fetch and return related objects) often results in much faster queries.
104+
105+
#### Declare Selected Fields
106+
107+
If you need more flexibility regarding the fields to be returned for an object type, you can specify a list of fields to include using the `fields` query parameter. For example, a request for `/api/dcim/sites/?fields=id,name,status,region` will return the following:
108+
109+
```json
110+
{
111+
"id": 2,
112+
"name": "DM-Akron",
113+
"status": {
114+
"value": "active",
115+
"label": "Active"
116+
},
117+
"region": {
118+
"id": 51,
119+
"url": "https://netbox/api/dcim/regions/51/",
120+
"display": "Ohio",
121+
"name": "Ohio",
122+
"slug": "us-oh",
123+
"description": "",
124+
"site_count": 0,
125+
"_depth": 2
126+
}
127+
}
128+
```
129+
130+
Like brief mode, this approach can significantly reduce the response time of an API request by omitting unneeded data.
131+
132+
#### Employ Pagination
133+
134+
Like the user interface, the REST API employs pagination to limit the number of objects returned in a single response. If a page size is not specified by the request (i.e. by passing `?limit=10`), NetBox will use the default size defined by [`PAGINATE_COUNT`](../configuration/default-values.md#paginate_count). The default page size is 50.
135+
136+
For some requests, especially those using brief mode or a minimal selection of fields, it may be desirable to specify a higher page size, so that fewer requests are needed to retrieve all objects. Appending `?limit=0` to the request effectively seeks to disable pagination. (Note, however, that the requested page size cannot exceed the value of [`MAX_PAGE_SIZE`](../configuration/miscellaneous.md#max_page_size), which defaults to 1,000.)
137+
138+
Complex API requests, which pull in many related objects, generate a relatively high load on the application, and generally benefit from reduced page size. If you find that your API requests are taking an inordinate amount of time, try reducing the page size from the default value so that fewer objects need to be returned for each request.
139+
140+
### GraphQL API
141+
142+
NetBox's read-only [GraphQL API](../integrations/graphql-api.md) offers an alternative to its REST API, and provides a very flexible means of retrieving data. GraphQL enables the client to request any object from a single endpoint, specifying only the desired attributes and relations. Many users prefer this to the more rigid structure of the REST API, but it's important to understand the trade-offs of crafting complex queries.
143+
144+
#### Avoid Overly Complex Queries
145+
146+
The primary benefit of the GraphQL API is that it allows the client to offload to the server the work of stitching together various related objects, which would require the client to make multiple requests to different endpoints if using the REST API. However, this advantage does not come for free: The more information that is requested in a single query, the more work the server needs to do to fetch the raw data from the database and render it into a GraphQL response. Very complex queries can yield dozens or hundreds of SQL queries on the backend, which increase the time it takes to render a response.
147+
148+
While it can be tempting to pack as much data as possible into a single GraphQL query, realize that there is a balance to be struck between minimizing the number of queries needed and avoiding complexity in the interest of performance. For example, while it is possible to retrieve via a single GraphQL API request all the IP addresses and all attached cables for every device in a site, it is probably more efficient (often _much_ more efficient) to make two or three separate requests and correlate the data locally.
149+
150+
#### Employ Pagination
151+
152+
Like the REST API, the GraphQL API supports pagination. Queries which return a large number of objects should employ pagination to limit the size of each response.
153+
154+
```
155+
{
156+
device_list(
157+
pagination: {limit: 100}
158+
) {
159+
id
160+
name
161+
serial
162+
status
163+
}
164+
}
165+
```

mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ nav:
126126
- Custom Scripts: 'customization/custom-scripts.md'
127127
- Best Practices:
128128
- Modeling Pluggable Transceivers: 'best-practices/modeling-pluggable-transceivers.md'
129+
- Performance Handbook: 'best-practices/performance-handbook.md'
129130
- Integrations:
130131
- REST API: 'integrations/rest-api.md'
131132
- GraphQL API: 'integrations/graphql-api.md'

0 commit comments

Comments
 (0)