diff --git a/README.md b/README.md
index 9ebb6be..9953f11 100644
--- a/README.md
+++ b/README.md
@@ -166,3 +166,81 @@ END
- Postgres does not natively support waiting for a finite specific amount of time, but this is emulated by looping through a temporary function.
- MariaDB does not accept infinite timeouts. very large numbers can be used instead.
- Float precision is not supported on MySQL/MariaDB.
+
+## Caveats about Transaction Levels
+
+### Key Principle
+
+> **Important**
+> Always avoid nested transactions when using advisory locks to ensure adherence to the **[S2PL (Strict 2-Phase Locking)](https://en.wikipedia.org/wiki/Two-phase_locking#Strict_two-phase_locking)** principle.
+
+### Recommended Approach
+
+When transactions and advisory locks are related, either locking approach can be applied.
+
+> **Note**
+> **Transaction-Level Locks:**
+> Acquire the lock at the transaction nesting level 1, then rely on automatic release mechanisms.
+>
+> ```php
+> if (DB::transactionLevel() > 1) {
+> throw new LogicException("Don't use nested transactions outside of this logic.");
+> }
+>
+> DB::advisoryLocker()
+> ->forTransaction()
+> ->lockOrFail('');
+> // critical section with transaction here
+> ```
+
+> **Note**
+> **Session-Level Locks:**
+> Acquire the lock at the transaction nesting level 0, then proceed to call `DB::transaction()` call.
+>
+> ```php
+> if (DB::transactionLevel() > 0) {
+> throw new LogicException("Don't use transactions outside of this logic.");
+> }
+>
+> $result = DB::advisoryLocker()
+> ->forSession()
+> ->withLocking('', fn (ConnectionInterface $conn) => $conn->transaction(function () {
+> // critical section with transaction here
+> }));
+> ```
+
+> **Warning**
+> When writing logic like this, [`DatabaseTruncation`](https://github.com/laravel/framework/blob/87b9e7997e178dfc4acd5e22fa8d77ba333c3abd/src/Illuminate/Foundation/Testing/DatabaseTruncation.php) must be used instead of [`RefreshDatabase`](https://github.com/laravel/framework/blob/87b9e7997e178dfc4acd5e22fa8d77ba333c3abd/src/Illuminate/Foundation/Testing/RefreshDatabase.php).
+
+### Considerations
+
+> **Warning**
+> **Transaction-Level Locks:**
+> Don't take transaction-level locks in nested transactions. They are unaware of Laravel's nested transaction emulation.
+
+> **Warning**
+> **Session-Level Locks:**
+> Don't take session-level locks in the transactions when the content to be committed by the transaction is related to the advisory locks.
+
+What would happen if we released a session-level lock within a transaction? Let's verify this with a timeline chart, assuming a `READ COMMITTED` isolation level on Postgres. The bank account X is operated from two sessions A and B concurrently.
+
+| Session A | Session B |
+|:-------------------------------------------------------------------|:------------------------------------------------------------------------------------------------------|
+| `BEGIN` | |
+| ︙ | `BEGIN` |
+| `pg_advisory_lock(X)` | ︙ |
+| ︙ | `pg_advisory_lock(X)` |
+| Fetch balance of User X
(Balance: 1000 USD) | ︙ |
+| ︙ | ︙ |
+| Deduct 800 USD if balance permits
(Balance: 1000 USD → 200 USD) | ︙ |
+| ︙ | ︙ |
+| `pg_advisory_unlock(X)` | ︙ |
+| ︙ | Fetch balance of User X
**(Balance: 1000 USD :heavy_exclamation_mark:)** |
+| ︙ | ︙ |
+| ︙ | Deduct 800 USD if balance permits
**(Balance: 1000 USD → 200 USD :bangbang:)** |
+| `COMMIT` | ︙ |
+| ︙ | `pg_advisory_unlock(X)` |
+| Fetch balance of User X
(Balance: 200 USD) | ︙ |
+| | `COMMIT` |
+| | ︙ |
+| | Fetch balance of User X
(**Balance: -600 USD** :interrobang::interrobang::interrobang:) |