Choosing the Right Backend for Collaboration Editor: Express vs FastAPI

:puzzle_piece: Context

When building a real-time collaborative editor (e.g., with Quill + Yjs or ProseMirror + Yjs), it’s crucial to select the right backend for handling synchronization, document state, and user awareness.

Two popular backend choices are:

  • Express.js (Node.js)
  • FastAPI (Python)

This guide compares both in the context of building a Yjs-powered collaboration server.


:balance_scale: FastAPI vs Express: Side-by-Side Comparison

Feature / Capability Express.js (Node.js) FastAPI (Python)
:electric_plug: Native Yjs Support :white_check_mark: Yes – with official y-websocket server :cross_mark: No – no official or stable Yjs WebSocket server
:counterclockwise_arrows_button: Yjs Sync Protocol (Step 1,2,3) :white_check_mark: Built-in support in JS ecosystem :cross_mark: Must be re-implemented manually
:bust_in_silhouette: Awareness (User presence, cursors) :white_check_mark: Supported via y-protocols/awareness :cross_mark: No support; must be ported from JS
:high_voltage: Binary WebSocket Messaging :white_check_mark: Optimized & native in Node :warning: Supported in ASGI, but requires extra effort
:brain: Use of lib0, y-protocols libs :white_check_mark: Native in JS :cross_mark: No equivalent in Python
:floppy_disk: Realtime DB persistence (Prisma) :white_check_mark: Easily integrated :warning: Requires API call to save Yjs state
:test_tube: Experimental Yjs implementations :cross_mark: Not needed :warning: ypy-websocket exists but not production-ready
:repeat_button: State persistence performance :white_check_mark: Direct access to database :cross_mark: Requires serialization and cross-service calls
:globe_showing_europe_africa: Community adoption and examples :white_check_mark: Widely used in production :cross_mark: Very limited real-world examples

:warning: Problem with Using FastAPI as a Separate Persistence Server

If you attempt to separate the Yjs WebSocket server (Node.js) and FastAPI as a separate microservice for saving state or metadata:

You introduce:

  • :stopwatch: Latency from cross-service HTTP requests
  • :red_exclamation_mark: Risk of race conditions between multiple simultaneous clients
  • :warning: Serialization overhead when converting binary updates to JSON
  • :brick: Infrastructure complexity (queues, retries, consistency checks)

Even if FastAPI is only used for saving state (e.g., docs_y_doc_state or prosemirror_delta), it will increase response time during document save, sync, or teardown.

:cross_mark: Therefore, for best performance, you should NOT delegate Yjs state saving to FastAPI via API calls.


There is an experimental project called ypy-websocket that attempts to replicate the Node.js WebSocket server in Python, but:

  • It is not production-ready
  • Lacks documentation, persistence, and extensibility
  • Has very limited adoption and maintenance

:white_check_mark: Final Recommendation

Stick with Express.js (Node.js) for your Yjs-based real-time collaboration backend.
It offers the best performance, native protocol support, and minimal friction for building collaborative editors.

Let the Node.js Yjs server handle:

  • WebSocket communication
  • Document state synchronization
  • Awareness (user presence, cursors)
  • Database persistence (e.g., via Prisma)

:snake: Use FastAPI Where It Shines

FastAPI is still an excellent companion service, especially for:

  • :locked_with_key: Authentication and authorization (e.g., JWT, OAuth2)
  • :office_worker: User and project metadata
  • :bar_chart: Admin dashboards and analytics
  • :toolbox: Business logic and validation APIs

:white_check_mark: Use FastAPI alongside your Node.js server — but not as a persistence layer for Yjs updates.



:pushpin: Summary

  • :white_check_mark: Node.js is the best environment for Yjs collaborative features
  • :cross_mark: FastAPI cannot replace Node.js for real-time document sync
  • :warning: Using FastAPI for saving Yjs state leads to latency and architectural complexity
  • :white_check_mark: Use a hybrid model: Node.js for sync, FastAPI for metadata/auth

:link: References