You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Currently, the SurrealDB async client does not support connection pooling. When multiple coroutines execute queries concurrently, they share a single WebSocket connection. This leads to concurrency issues because the WebSocket protocol does not allow multiple simultaneous recv() operations. As a result, applications using SurrealDB in an asynchronous environment may encounter the following error:
websockets.exceptions.ConcurrencyError: cannot call recv while another coroutine is already running recv or recv_streaming
To avoid this, developers must serialize queries using asyncio.Lock or an external task queue. However, this approach creates a bottleneck, significantly limiting throughput in high-concurrency scenarios.
Describe the solution
To improve scalability and concurrency, SurrealDB should implement connection pooling in its async WebSocket client. This would allow multiple WebSocket connections to be maintained, distributing queries among them instead of relying on a single connection.
Key features of the proposed solution:
1. Pool Management: Maintain a configurable number of WebSocket connections (e.g., pool_size=5 by default).
2. Automatic Connection Assignment: When a query is made, assign it to an available connection.
3. Efficient Reuse: After a query is executed, the connection should return to the pool for reuse.
4. Graceful Scaling: If all connections are busy, either queue the query or allow an optional expansion of the pool.
5. Automatic Cleanup: Close unused or idle connections after a configurable timeout.
Implementation Example (Python)
A simple connection pool could be implemented as follows:
import asyncio
from surrealdb import Surreal
class SurrealDBPool:
def __init__(self, pool_size=5):
self.pool = asyncio.Queue()
self.pool_size = pool_size
async def initialize_pool(self):
for _ in range(self.pool_size):
db = Surreal()
await db.connect("ws://localhost:8000")
await self.pool.put(db) # Store connection in queue
async def query(self, query_string):
db = await self.pool.get() # Get an available connection
try:
return await db.query(query_string)
finally:
await self.pool.put(db) # Return connection to pool
✅ Scales efficiently for high-concurrency applications
✅ Eliminates WebSocket concurrency errors
✅ Reduces query latency by preventing bottlenecks
Why This Matters
Adding built-in connection pooling to the SurrealDB async client would:
• Provide out-of-the-box concurrency handling, reducing the need for workarounds.
• Improve performance and responsiveness for applications handling frequent queries.
• Ensure a better developer experience, making SurrealDB easier to integrate with async frameworks like Quart, FastAPI, and Django Async.
Alternative methods
I have tried to serialize queries using asyncio.Lock or an external task queue. However, this approach creates a bottleneck, significantly limiting throughput in high-concurrency scenarios
Hey @dyleeeeeeee thanks for the suggestion. I have raised it with the team and we are discussing it as it has gel with the other SDKs and surrealDB server. I have built a side project that is unoffical that pools connections here. It also does migrations etc. This is for quicker iterations with experimental features that might find their way into the official SDK.
Hello Max!
I really appreciate your response and I am looking forward to coming updates on this issue as my company is building a SaaS application and using SurrealDB is proving to be the best decision we have made so far.
In the meantime, I created a lightweight library with sufficient features in also handling this implementation, here!.
I appreciate the effort from the SurrealDB team, you guys are redefining the possibilities of a database.
Is your feature request related to a problem?
Currently, the SurrealDB async client does not support connection pooling. When multiple coroutines execute queries concurrently, they share a single WebSocket connection. This leads to concurrency issues because the WebSocket protocol does not allow multiple simultaneous recv() operations. As a result, applications using SurrealDB in an asynchronous environment may encounter the following error:
websockets.exceptions.ConcurrencyError: cannot call recv while another coroutine is already running recv or recv_streaming
To avoid this, developers must serialize queries using asyncio.Lock or an external task queue. However, this approach creates a bottleneck, significantly limiting throughput in high-concurrency scenarios.
Describe the solution
To improve scalability and concurrency, SurrealDB should implement connection pooling in its async WebSocket client. This would allow multiple WebSocket connections to be maintained, distributing queries among them instead of relying on a single connection.
Key features of the proposed solution:
1. Pool Management: Maintain a configurable number of WebSocket connections (e.g., pool_size=5 by default).
2. Automatic Connection Assignment: When a query is made, assign it to an available connection.
3. Efficient Reuse: After a query is executed, the connection should return to the pool for reuse.
4. Graceful Scaling: If all connections are busy, either queue the query or allow an optional expansion of the pool.
5. Automatic Cleanup: Close unused or idle connections after a configurable timeout.
Implementation Example (Python)
A simple connection pool could be implemented as follows:
✅ Scales efficiently for high-concurrency applications
✅ Eliminates WebSocket concurrency errors
✅ Reduces query latency by preventing bottlenecks
Why This Matters
Adding built-in connection pooling to the SurrealDB async client would:
• Provide out-of-the-box concurrency handling, reducing the need for workarounds.
• Improve performance and responsiveness for applications handling frequent queries.
• Ensure a better developer experience, making SurrealDB easier to integrate with async frameworks like Quart, FastAPI, and Django Async.
Alternative methods
I have tried to serialize queries using asyncio.Lock or an external task queue. However, this approach creates a bottleneck, significantly limiting throughput in high-concurrency scenarios
SurrealDB version
surreal x.x.x
surrealdb.py version
1.x.x
Contact Details
doubra.ak@gmail.com
Is there an existing issue for this?
Code of Conduct
The text was updated successfully, but these errors were encountered: