Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
"GDPR",
"Github",
"GTM",
"Gunicorn",
"IAM",
"IDSync",
"IDFA",
Expand Down
72 changes: 72 additions & 0 deletions docs/server-core/python/_faqs.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
## Process Forking and WSGI Servers

### ⚠️ Warning: Do not fork processes after Statsig initialization

**Important:** Never fork processes after calling `statsig.initialize()`. Doing so will put Statsig in a weird state and may cause deadlocks.

The Python Core SDK uses internal threading and async runtime components that do not work correctly when copied across process boundaries. When a process forks after initialization, these components can become corrupted, leading to:

- Deadlocks in event logging
- Hanging initialization calls
- Unpredictable SDK behavior
- Silent failures in feature evaluation

### Correct initialization for WSGI servers

For production deployments using WSGI servers like uWSGI or Gunicorn, ensure Statsig is initialized **after** the worker processes are forked, not in the main process.

#### ✅ Correct: uWSGI example

```python
# app.py
from statsig_python_core import Statsig, StatsigOptions
from flask import Flask

app = Flask(__name__)
statsig = None

def init_statsig():
global statsig
if statsig is None:
options = StatsigOptions()
options.environment = "production"
statsig = Statsig("your-server-secret-key", options)
statsig.initialize().wait()

# Initialize in each worker process
@app.before_first_request
def before_first_request():
init_statsig()

@app.route('/')
def index():
# Use statsig here
return "Hello World"
```

```ini
# uwsgi.ini
[uwsgi]
module = app:app
master = true
processes = 4
# Statsig will be initialized in each worker process
```

#### ✅ Correct: Gunicorn example

```python
# gunicorn_config.py
def post_fork(server, worker):
# Initialize Statsig after worker process is forked
from app import init_statsig
init_statsig()

# app.py - same as uWSGI example above
```

```bash
# Start Gunicorn with post-fork hook
gunicorn --config gunicorn_config.py app:app
```