Skip to content

feat: support configurable MEMMACHINE_WORKERS and fix circular import - #903

Merged
sscargal merged 1 commit into
MemMachine:mainfrom
sscargal:feature/fastapi-workers
Jan 6, 2026
Merged

sscargal merged 1 commit into
MemMachine:mainfrom
sscargal:feature/fastapi-workers

Conversation

@sscargal

@sscargal sscargal commented Jan 6, 2026

Copy link
Copy Markdown
Contributor

Purpose of the change

This is the first phase of improving MemMachine's overall performance, specifically by increasing the number of users and requests per second (RPS).

Description

By adding a worker pool to FastAPI, we allow users to configure the number of FastAPI workers to handle requests and connections. We default to 1, as we had before. The number of workers is determined by MEMMACHINE_WORKERS environment variable in .env.

Users are encouraged to tune the number of workers based on the system resources (vCPU and memory capacity) and the anticipated user load.

Note 1: We need to use uvicorn.run instead of uvicorn.Server, as the latter doesn't support forking new processes, whereas' uvicorn.run' does.

Note 2: When using this new uvicorn.run and forking approach, it highlighted a race condition where memmachine.common wasn't imported early enough, so this was added to __init__.py to resolve this.

Fixes/Closes

Fixes #902

Relates to #837

Type of change

  • New feature (non-breaking change which adds functionality)

How Has This Been Tested?

Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration.

  • Manual verification (list step-by-step instructions)

Test Results: [Attach logs, screenshots, or relevant output]

Default MEMMACHINE_WORKERS=1

This doesn't change how MemMachine works in existing versions up to v0.2.2.

By default, docker top shows the primary process (1 worker).

$ docker top memmachine-app
UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
root                2367044             2367021             0                   00:04               ?                   00:00:00            sh -c memmachine-server
root                2367124             2367044             14                  00:04               ?                   00:00:06            /app/.venv/bin/python3 /app/.venv/bin/memmachine-server

The logs now report the number of worker(s):

memmachine-app       | 2026-01-06 00:04:17,110 [INFO] memmachine.server.app - Starting server with 1 worker

Default MEMMACHINE_WORKERS=5

When we set the number of workers to 5, we see 5 spawned processes running inside the Docker container.

memmachine-app       | 2026-01-06 00:07:08,834 [INFO] memmachine.server.app - Starting server with 5 workers
$ docker top memmachine-app
UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
root                2369995             2369971             0                   00:07               ?                   00:00:00            sh -c memmachine-server
root                2370061             2369995             14                  00:07               ?                   00:00:05            /app/.venv/bin/python3 /app/.venv/bin/memmachine-server
root                2370291             2370061             0                   00:07               ?                   00:00:00            /app/.venv/bin/python3 -c from multiprocessing.resource_tracker import main;main(6)
root                2370292             2370061             9                   00:07               ?                   00:00:03            /app/.venv/bin/python3 -c from multiprocessing.spawn import spawn_main; spawn_main(tracker_fd=7, pipe_handle=9) --multiprocessing-fork
root                2370293             2370061             9                   00:07               ?                   00:00:02            /app/.venv/bin/python3 -c from multiprocessing.spawn import spawn_main; spawn_main(tracker_fd=7, pipe_handle=13) --multiprocessing-fork
root                2370294             2370061             9                   00:07               ?                   00:00:02            /app/.venv/bin/python3 -c from multiprocessing.spawn import spawn_main; spawn_main(tracker_fd=7, pipe_handle=17) --multiprocessing-fork
root                2370295             2370061             9                   00:07               ?                   00:00:03            /app/.venv/bin/python3 -c from multiprocessing.spawn import spawn_main; spawn_main(tracker_fd=7, pipe_handle=21) --multiprocessing-fork
root                2370296             2370061             9                   00:07               ?                   00:00:02            /app/.venv/bin/python3 -c from multiprocessing.spawn import spawn_main; spawn_main(tracker_fd=7, pipe_handle=25) --multiprocessing-fork

Checklist

  • I have signed the commit(s) within this pull request
  • My code follows the style guidelines of this project (See STYLE_GUIDE.md)
  • I have performed a self-review of my own code
  • I have commented my code
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • New and existing unit tests pass locally with my changes
  • I have checked my code and corrected any misspellings

Maintainer Checklist

  • Confirmed all checks passed
  • Contributor has signed the commit(s)
  • Reviewed the code
  • Run, Tested, and Verified the change(s) work as expected

Screenshots/Gifs

See outputs above from the logs and terminal.

Further comments

While this PR allows users to create a FastAPI worker pool, there are two things to note:

  1. Increasing the number of workers DOES NOT, at least at this point in time, increase Locust performance testing. In some situations, adding more workers can reduce requests-per-second due to serialization issues in the core code that must be identified and resolved for true parallelism. That's why this is Phase 1 of n.
  2. We do not try to automatically determine the worker thread pool count, which is commonly done based on the number of vCPUs, such as using (os.cpu_count() - 1), as this is often inaccurate in container environments (reporting host CPUs vs container limits). We leave it to the user to configure MEMMACHINE_WORKERS based on their allocated vCPUs to avoid creating excessive worker processes at startup.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds configurable worker pool support to MemMachine's FastAPI server to improve performance and scalability. The number of workers is controlled via the MEMMACHINE_WORKERS environment variable, defaulting to 1 to maintain backward compatibility.

  • Replaces uvicorn.Server with uvicorn.run to enable multi-process worker support
  • Adds MEMMACHINE_WORKERS environment variable configuration with validation
  • Fixes a circular import race condition by importing memmachine.common.api early in __init__.py

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
src/memmachine/server/app.py Implements configurable worker pool with environment variable parsing and validation; converts async start() to synchronous start_http() using uvicorn.run
src/memmachine/init.py Adds early import of memmachine.common.api to prevent race condition in multi-worker scenarios
sample_configs/env.dockercompose Adds MEMMACHINE_WORKERS=1 configuration example
docker-compose.yml Passes MEMMACHINE_WORKERS environment variable to the app container with default value of 1

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/memmachine/server/app.py
Comment thread src/memmachine/server/app.py

@jgong jgong left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks!

@sscargal
sscargal merged commit 6e876c6 into MemMachine:main Jan 6, 2026
41 of 42 checks passed
@sscargal
sscargal deleted the feature/fastapi-workers branch January 6, 2026 22:12
o-love pushed a commit that referenced this pull request Jan 23, 2026
SarahScargall pushed a commit to SarahScargall/MemMachine that referenced this pull request Jan 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feat]: Support a pool of FastAPI workers in @app.py for scale-up

4 participants