Skip to content

Commit 7e8f32e

Browse files
docs: reinstate Edge Proxy reference documentation (#6274)
1 parent 8efb108 commit 7e8f32e

File tree

2 files changed

+286
-40
lines changed

2 files changed

+286
-40
lines changed
Lines changed: 282 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,72 +1,314 @@
11
---
2+
sidebar_label: Edge Proxy
23
title: Edge Proxy
34
sidebar_position: 3
45
---
56

6-
The Flagsmith Edge Proxy is a service that you host yourself, which allows you to run an instance of the Flagsmith Engine close to your servers. If you are running Flagsmith within a server-side environment and you want to have very low latency flags, you have two options:
7+
The [Edge Proxy](/performance/edge-proxy) runs as a
8+
[Docker container](https://hub.docker.com/repository/docker/flagsmith/edge-proxy) with no external dependencies.
9+
It connects to the Flagsmith API to download environment documents, and your Flagsmith client applications connect to it
10+
using [remote flag evaluation](/integrating-with-flagsmith/sdks#remote-evaluation).
711

8-
1. Run the Edge Proxy within your own infrastructure and connect to it from your server-side SDKs
9-
2. Run your server-side SDKs in [Local Evaluation Mode](/integrating-with-flagsmith/sdks/server-side#local-evaluation).
12+
The examples below assume you have a configuration file located at `./config.json`. Your Flagsmith client applications
13+
can then consume the Edge Proxy by setting their API URL to `http://localhost:8000/api/v1/`.
1014

11-
The main benefit to running the Edge Proxy is that you reduce your polling requests against the Flagsmith API itself.
15+
<details>
16+
<summary>Docker CLI</summary>
17+
```
18+
docker run \
19+
-v ./config.json:/app/config.json \
20+
-p 8000:8000 \
21+
flagsmith/edge-proxy:latest
22+
```
23+
</details>
24+
25+
<details>
26+
<summary>Docker Compose</summary>
27+
```yaml title="compose.yaml"
28+
services:
29+
edge_proxy:
30+
image: flagsmith/edge-proxy:latest
31+
volumes:
32+
- type: bind
33+
source: ./config.json
34+
target: /app/config.json
35+
ports:
36+
- '8000:8000'
37+
```
38+
</details>
39+
40+
## Configuration
41+
42+
The Edge Proxy can be configured with any combination of:
43+
44+
- Environment variables.
45+
- A JSON configuration file, by default located at `/app/config.json` in the Edge Proxy container.
46+
47+
Environment variables take priority over their corresponding options defined in the configuration file.
48+
49+
Environment variable names are case-insensitive, and are processed using
50+
[Pydantic](https://docs.pydantic.dev/2.7/concepts/pydantic_settings/#environment-variable-names).
51+
52+
### Example configuration
53+
54+
<details>
55+
56+
<summary>Configuration file</summary>
57+
58+
```json title="/app/config.json"
59+
{
60+
"environment_key_pairs": [
61+
{
62+
"server_side_key": "ser.your_server_side_key_1",
63+
"client_side_key": "your_client_side_key_1"
64+
}
65+
],
66+
"api_poll_frequency_seconds": 5,
67+
"logging": {
68+
"log_level": "DEBUG",
69+
"log_format": "json"
70+
}
71+
}
72+
```
73+
74+
</details>
75+
76+
<details>
77+
78+
<summary>Environment variables</summary>
79+
80+
```ruby
81+
ENVIRONMENT_KEY_PAIRS='[{"server_side_key":"ser.your_server_side_key_1","client_side_key":"your_client_side_key_1"}]'
82+
API_POLL_FREQUENCY_SECONDS=5
83+
LOGGING='{"log_level":"DEBUG","log_format":"json"}'
84+
```
85+
86+
</details>
87+
88+
### Basic settings
89+
90+
#### `environment_key_pairs`
91+
92+
Specifies which environments to poll environment documents for. Each environment requires a server-side key and its
93+
corresponding client-side key.
94+
95+
```json
96+
"environment_key_pairs": [{
97+
"server_side_key": "ser.your_server_side_key",
98+
"client_side_key": "your_client_side_environment_key"
99+
}]
100+
```
101+
102+
#### `api_url`
103+
104+
If you are self-hosting Flagsmith, set this to your API URL:
105+
106+
```json
107+
"api_url": "https://flagsmith.example.com/api/v1"
108+
```
109+
110+
#### `api_poll_frequency_seconds`
111+
112+
How often to poll the Flagsmith API for changes, in seconds. Defaults to 10.
113+
114+
```json
115+
"api_poll_frequency_seconds": 30
116+
```
117+
118+
#### `api_poll_timeout_seconds`
119+
120+
The request timeout when trying to retrieve new changes, in seconds. Defaults to 5.
121+
122+
```json
123+
"api_poll_timeout_seconds": 1
124+
```
12125

13-
The main benefit to running server-side SDKs in [Local Evaluation Mode](/integrating-with-flagsmith/sdks/server-side#local-evaluation) is that you get the lowest possible latency.
126+
#### `allow_origins`
14127

15-
## How Does It Work
128+
Set a value for the `Access-Control-Allow-Origin` header. Defaults to `*`.
16129

17-
:::info
130+
```json
131+
"allow_origins": "https://www.example.com"
132+
```
133+
134+
### Endpoint caches
135+
136+
#### `endpoint_caches`
137+
138+
Enables a LRU cache per endpoint.
139+
140+
Optionally, specify the LRU cache size with `cache_max_size`. Defaults to 128.
18141

19-
The Edge Proxy has the same [caveats as running our SDK in Local Evaluation mode.](/integrating-with-flagsmith/sdks/server-side#local-evaluation).
142+
```json
143+
"endpoint_caches": {
144+
"flags": {
145+
"use_cache": false
146+
},
147+
"identities": {
148+
"use_cache": true,
149+
"cache_max_size": 1000,
150+
}
151+
}
152+
```
153+
154+
### Server settings
20155

21-
:::
156+
#### `server.proxy_headers`
22157

23-
You can think of the Edge Proxy as a copy of our Python Server-Side SDK, running in [Local Evaluation Mode](/integrating-with-flagsmith/sdks/server-side#local-evaluation), with an API interface that is compatible with the Flagsmith SDK API.
158+
When set to `true`, the Edge Proxy will use the `X-Forwarded-For` and `X-Forwarded-Proto` HTTP headers to determine
159+
client IP addresses. This is useful if the Edge Proxy is running behind a reverse proxy, and you want the
160+
[access logs](#logging.override) to show the real IP addresses of your clients.
24161

25-
The Edge Proxy runs as a lightweight Docker container. It connects to the Flagsmith API (either powered by us at api.flagsmith.com or self-hosted by you) to get environment flags and segment rules. You can then point the Flagsmith SDKs to your Edge Proxy; it implements all the current SDK endpoints. This means you can serve a very large number of requests close to your infrastructure and users, at very low latency. Check out the [architecture below](#architecture).
162+
By default, only the loopback address is trusted. This can be changed with the [`FORWARDED_ALLOW_IPS` environment
163+
variable](#environment-variables).
26164

27-
The Proxy also acts as a local cache, allowing you to make requests to the Proxy without hitting the core API.
165+
```json
166+
"server": {
167+
"proxy_headers": true
168+
}
169+
```
28170

29-
## Performance
171+
```
172+
SERVER_PROXY_HEADERS=true
173+
```
30174
31-
The Edge Proxy can currently serve ~2,000 requests per second (RPS) at a mean latency of ~7ms on an M1 MacBook Pro with a simple set of flags. Working with more complex environments with many segment rules will bring this RPS number down.
175+
### Logging
32176
33-
It is stateless and hence close to perfectly scalable when deployed behind a load balancer.
177+
#### `logging.log_level`
34178
35-
## Managing Traits
179+
Choose a logging level from `"CRITICAL"`, `"ERROR"`, `"WARNING"`, `"INFO"`, `"DEBUG"`. Defaults to `"INFO"`.
36180
37-
There is one caveat with the Edge Proxy. Because it is entirely stateless, it is not able to persist trait data into any sort of data store. This means that you _have_ to provide the full complement of traits when requesting the flags for a particular identity. Our SDKs all provide relevant methods to achieve this. An example using `curl` would read as follows:
181+
```json
182+
"logging": {"log_level": "DEBUG"}
183+
```
184+
185+
#### `logging.log_format`
186+
187+
Choose a logging format between `"generic"` and `"json"`. Defaults to `"generic"`.
188+
189+
```json
190+
"logging": {"log_format": "json"}
191+
```
192+
193+
#### `logging.log_event_field_name`
194+
195+
Set a name used for human-readable log entry field when logging events in JSON. Defaults to `"message"`.
196+
197+
```json
198+
"logging": {"log_event_field_name": "event"}
199+
```
38200

39-
```bash
40-
curl -X "POST" "http://localhost:8000/api/v1/identities/?identifier=do_it_all_in_one_go_identity" \
41-
-H 'X-Environment-Key: n9fbf9h3v4fFgH3U3ngWhb' \
42-
-H 'Content-Type: application/json; charset=utf-8' \
43-
-d $'{
44-
"traits": [
45-
{
46-
"trait_value": 123.5,
47-
"trait_key": "my_trait_key"
201+
#### `logging.colour`
202+
203+
Added in [2.13.0](https://github.com/Flagsmith/edge-proxy/releases/tag/v2.13.0).
204+
205+
Set to `false` to disable coloured output. Useful when outputting the log to a file.
206+
207+
#### `logging.override`
208+
209+
Added in [2.13.0](https://github.com/Flagsmith/edge-proxy/releases/tag/v2.13.0).
210+
211+
Accepts
212+
[Python-compatible logging settings](https://docs.python.org/3/library/logging.config.html#configuration-dictionary-schema)
213+
in JSON format. You're able to define custom formatters, handlers and logger configurations. For example, to log
214+
everything a file, one can set up own file handler and assign it to the root logger:
215+
216+
```json
217+
"logging": {
218+
"override": {
219+
"handlers": {
220+
"file": {
221+
"level": "INFO",
222+
"class": "logging.FileHandler",
223+
"filename": "edge-proxy.log",
224+
"formatter": "json"
225+
}
226+
},
227+
"loggers": {
228+
"": {
229+
"handlers": ["file"],
230+
"level": "INFO",
231+
"propagate": true
232+
}
233+
}
234+
}
235+
}
236+
```
237+
238+
Or, log access logs to file in generic format while logging everything else to stdout in JSON:
239+
240+
```json
241+
"logging": {
242+
"override": {
243+
"handlers": {
244+
"file": {
245+
"level": "INFO",
246+
"class": "logging.FileHandler",
247+
"filename": "edge-proxy.log",
248+
"formatter": "generic"
249+
}
48250
},
49-
{
50-
"trait_value": true,
51-
"trait_key": "my_other_key"
251+
"loggers": {
252+
"": {
253+
"handlers": ["default"],
254+
"level": "INFO"
255+
},
256+
"uvicorn.access": {
257+
"handlers": ["file"],
258+
"level": "INFO",
259+
"propagate": false
260+
}
52261
}
53-
],
54-
"identifier": "do_it_all_in_one_go_identity"
55-
}'
262+
}
263+
}
56264
```
57265

58-
Note that the Edge Proxy will currently _not_ send the trait data back to the Core API.
266+
When adding logger configurations, you can use the `"default"` handler which writes to stdout and uses formatter
267+
specified by the [`"logging.log_format"`](#logginglog_format) setting.
268+
269+
### Health checks
270+
271+
The Edge Proxy exposes two health check endpoints:
272+
273+
* `/proxy/health/liveness`: Always responds with a 200 status code. Use this health check to determine if the Edge
274+
Proxy is alive and able to respond to requests.
275+
* `/proxy/health/readiness`: Responds with a 200 status if the Edge Proxy was able to fetch all its configured
276+
environment documents within a configurable grace period. This allows the Edge Proxy to continue reporting as healthy
277+
even if the Flagsmith API is temporarily unavailable. This health check is also available at `/proxy/health`.
59278

60-
## Deployment and Configuration
279+
You should point your orchestration health checks to these endpoints.
61280

62-
Please see the [hosting documentation](/deployment-self-hosting/hosting-guides/docker).
281+
#### `health_check.environment_update_grace_period_seconds`
63282

64-
## Architecture
283+
Default: `30`.
65284

66-
The standard Flagsmith architecture:
285+
The number of seconds to allow per environment key pair before the environment data stored by the Edge Proxy is
286+
considered stale.
287+
288+
When set to `null`, cached environment documents are never considered stale, and health checks will succeed if all
289+
environments were successfully fetched at some point since the Edge Proxy started.
290+
291+
The effective grace period depends on how many environments the Edge Proxy is configured to serve. It can be calculated
292+
using the following pseudo-Python code:
293+
294+
```python
295+
total_grace_period_seconds = api_poll_frequency + (environment_update_grace_period_seconds * len(environment_key_pairs))
296+
if last_updated_all_environments_at < datetime.now() - timedelta(seconds=total_grace_period_seconds):
297+
# Data is stale
298+
return 500
299+
# Data is not stale
300+
return 200
301+
```
67302

68-
![Image](/img/edge-proxy-existing.svg)
303+
### Environment variables
69304

70-
With the proxy added to the mix:
305+
Some Edge Proxy settings can only be set using environment variables:
71306

72-
![Image](/img/edge-proxy-proxy.svg)
307+
- `WEB_CONCURRENCY` The number of [Uvicorn](https://www.uvicorn.org/) workers. Defaults to `1`, which is
308+
[recommended when running multiple Edge Proxy containers behind a load balancer](https://fastapi.tiangolo.com/deployment/docker/#one-load-balancer-multiple-worker-containers).
309+
If running on a single node, set this [based on your number of CPU cores and threads](https://docs.gunicorn.org/en/latest/design.html#how-many-workers).
310+
- `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, `NO_PROXY`: These variables let you configure an HTTP proxy that the
311+
Edge Proxy should use for all its outgoing HTTP requests.
312+
[Learn more](https://www.python-httpx.org/environment_variables)
313+
- `FORWARDED_ALLOW_IPS`: Which IPs to trust for determining client IP addresses when using the `proxy_headers` option.
314+
For more details, see the [Uvicorn documentation](https://www.uvicorn.org/settings/#http).

docs/vercel.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,10 @@
312312
"source": "/deployment/configuration/authentication/SAML",
313313
"destination": "/administration-and-security/access-control/saml"
314314
},
315+
{
316+
"source": "/deployment/hosting/locally-edge-proxy",
317+
"destination": "/deployment-self-hosting/edge-proxy"
318+
},
315319
{
316320
"source": "/integrations/amplitude",
317321
"destination": "/third-party-integrations/analytics/amplitude"

0 commit comments

Comments
 (0)