Skip to content

Use nested sessions rather than starting new connections on each transaction#4549

Closed
bitbyt3r wants to merge 4 commits intomainfrom
nested_sessions
Closed

Use nested sessions rather than starting new connections on each transaction#4549
bitbyt3r wants to merge 4 commits intomainfrom
nested_sessions

Conversation

@bitbyt3r
Copy link
Copy Markdown
Member

@bitbyt3r bitbyt3r commented Mar 7, 2026

Before this change, it's opening a whole new connection for each with Session() as session:
Screenshot 2026-03-07 at 16 37 15

After this change it reuses the connection, and just opens a nested session:
Screenshot 2026-03-07 at 16 35 46


# If we're already in a session use a nested session rather than opening a new connection
if kwargs.get('bind') == getattr(req, 'db_connection', None) and req.db_connection.in_transaction():
session.begin_nested()
Copy link
Copy Markdown
Member

@kitsuta kitsuta Mar 7, 2026

Choose a reason for hiding this comment

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

Running begin_nested actually flushes the current session to the database along with a SAVEPOINT call:

When Session.begin_nested() is called, the Session first flushes all currently pending state to the database;

Since the intent of these calls is typically just to acquire a session without having one passed to the function, I'd say the better behavior would be to just return the current session. begin_nested can still easily be called anywhere we want to create savepoint/rollback behavior, such as when we run validations.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It looks like running begin_nested effectively breaks our is_new property, which is used pretty extensively, so we definitely should not run this in the background.

kitsuta added a commit that referenced this pull request Mar 17, 2026
This is a redux of #4549 with a slightly different approach: instead of always returning a 'nested' session (it's not actually nested -- more on that below), we just return the current session unless a flag is passed to specifically enable nesting. We add this flag to the few cases where a rollback is used in a `with Session() as session` block.

True nested sessions are no longer supported in SQLAlchemy. Instead, when you run `session.begin_nested`, the session is flushed to the database along with the SAVEPOINT command. This allows you to run session.rollback() to go back to the savepoint.

The problem is, we inspect session state for objects -- particularly via the `is_new` property. Since running session.begin_nested flushes the current session, `is_new` returns False for any objects that were pending when you made a 'nested' session. We don't want that in most cases, so we want to use nested sessions sparingly.
@kitsuta
Copy link
Copy Markdown
Member

kitsuta commented Mar 17, 2026

This branch has a bunch of opentelemetry stuff in it, so I copied the relevant code to #4552 to merge in!

@kitsuta kitsuta closed this Mar 17, 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.

2 participants