title: aiohttp: rate limiting parallel requests
body: <p>APIs often have rate limits that users have to follow. As an example let's take 50 requests/second. Sequential requests take 0.5-1 second and thus are too slow to come close to that limit. Parallel requests with aiohttp, however, exceed the rate limit.</p>
  
  <p>To poll the API as fast as allowed, one needs to rate limit parallel calls.</p>
  
  <p>Examples that I found so far decorate <code>session.get</code>, approximately like so:</p>
  
  <pre><code>session.get = rate_limited(max_calls_per_second)(session.get)
  </code></pre>
  
  <p>This works well for sequential calls. Trying to implement this in parallel calls does not work as intended.</p>
  
  <p>Here's some code as example:</p>
  
  <pre><code>async with aiohttp.ClientSession() as session:
      session.get = rate_limited(max_calls_per_second)(session.get)
      tasks = (asyncio.ensure_future(download_coroutine(  
            timeout, session, url)) for url in urls)
      process_responses_function(await asyncio.gather(*tasks))
  </code></pre>
  
  <p>The problem with this is that it will rate-limit the <strong>queueing</strong> of the tasks. The execution with <code>gather</code> will still happen more or less at the same time. Worst of both worlds ;-).</p>
  
  <p>Yes, I found a similar question right here <a href="https://stackoverflow.com/questions/35196974/aiohttp-set-maximum-number-of-requests-per-second">aiohttp: set maximum number of requests per second</a>, but neither replies answer the actual question of limiting the rate of requests. Also <a href="https://quentin.pradet.me/blog/how-do-you-rate-limit-calls-with-aiohttp.html" rel="noreferrer">the blog post from Quentin Pradet</a> works only on rate-limiting the queueing.</p>
  
  <p>To wrap it up: How can one limit the <em>number of requests per second</em> for parallel <code>aiohttp</code> requests?</p>