         }
     }
     
-    private func didCommit() {
+    // Called from sqlite3_commit_hook
+    private func databaseWillCommit() throws {
+        // Time to send all buffered events
+        
+        let eventsBuffer = savepointStack.eventsBuffer
+        savepointStack.clear()
+        
+        for (event, observations) in eventsBuffer {
+            for observation in observations {
+                event.send(to: observation)
+            }
+        }
+        
+        for observation in transactionObservations {
+            try observation.databaseWillCommit()
+        }
+    }
+    
+    // Called from updateStatementDidExecute
+    private func databaseDidCommit() {
         savepointStack.clear()
         
         for observation in transactionObservations {

        cleanupTransactionObservations()
    }
    
    private func didRollback(notifyTransactionObservers: Bool) {
        savepointStack.clear()
        
        if notifyTransactionObservers {

        #if SQLITE_ENABLE_PREUPDATE_HOOK
            sqlite3_preupdate_hook(database.sqliteConnection, { (brokerPointer, databaseConnection, updateKind, databaseNameCString, tableNameCString, initialRowID, finalRowID) in
                let broker = Unmanaged<DatabaseObservationBroker>.fromOpaque(brokerPointer!).takeUnretainedValue()
                broker.databaseWillChange(with: DatabasePreUpdateEvent(
                    connection: databaseConnection!,
                    kind: DatabasePreUpdateEvent.Kind(rawValue: updateKind)!,
                    initialRowID: initialRowID,
