Phase 13 of 25 · Topic 13.5

Concurrency Throttling with asyncio.Semaphore

1Concept

An `asyncio.Semaphore` manages an internal counter to restrict the maximum number of concurrent operations, preventing microservices from overwhelming downstream databases or exceeding API rate limits.

2Architecture Diagram

Semaphore(limit=2):
[ Request 1: Granted ] [ Request 2: Granted ] [ Request 3: Waiting until 1 completes ]

3Code Example

Python 3.12
import asyncio

semaphore = asyncio.Semaphore(2) # Max 2 concurrent tasks

async def limited_access_resource(task_id: int):
    async with semaphore:
        print(f"Task {task_id} acquired access lock.")
        await asyncio.sleep(0.02)
        print(f"Task {task_id} released access lock.")

async def main():
    await asyncio.gather(*(limited_access_resource(i) for i in range(1, 4)))

asyncio.run(main())

4Expected Output

Task 1 acquired access lock.
Task 2 acquired access lock.
Task 1 released access lock.
Task 3 acquired access lock.
Task 2 released access lock.
Task 3 released access lock.

5Key Takeaways

  • Use Semaphores to throttle external API rate limits (e.g. OpenAI / Stripe rate caps).
  • Always acquire semaphores with `async with semaphore:` to ensure release.
  • `asyncio.BoundedSemaphore` prevents releasing more times than acquired.