Skip to content

Implement distributed rate limiting for downloads#357

Merged
don-vip merged 1 commit intomasterfrom
feat/download-rate-limiting
Apr 2, 2026
Merged

Implement distributed rate limiting for downloads#357
don-vip merged 1 commit intomasterfrom
feat/download-rate-limiting

Conversation

@Amdrel
Copy link
Copy Markdown
Collaborator

@Amdrel Amdrel commented Apr 2, 2026

Description

This patch aims to help reduce the risk of blocks from YouTube (see #320) by restricting video2commons from performing concurrent downloads of videos from YouTube and introducing a delay between requests. Concurrent downloads are restricted by using a lock stored in Redis that allows only one worker at a time to download videos.

Note: It seems the block is active again so we won't be able to see how successful this patch is until the existing one expires.

Changes

  • Added a new context manager named YoutubeDLRateLimited that wraps yt_dlp.YoutubeDL
    • This applies rate-limiting parameters and acquires a distributed lock in Redis that prevents concurrent requests to rate-limited sites between multiple workers
    • The frontend (flask) and backend (workers) use separate locks since the blocks on the backend don't affect the frontend due to having different public IPs (see the source param)
  • Only YouTube domains are rate-limited currently and other URLs bypass locking entirely
    • The code can be easily extended to work with other sites if needed, though I'm doubtful this will happen anytime soon as we've only have had blocking issues with YouTube from what I've seen
  • Once the lock is acquired, rate-limiting is done via sleep delays that vary
    • Media downloads have a delay of 10 seconds
    • Extraction requests wait 3 seconds
    • Subtitle downloads wait 6 seconds
    • The frontend uses a shorter lock timeout of 60 seconds and an extraction delay of 1 second as it seems doing those kinds of requests in isolation hasn't caused us any issue yet
  • Added logging.basicConfig(level=logging.INFO) to the worker and flask app since logging wasn't setup and having the diagnostic information for concurrent locks might be useful if we run into any issues

Deployment

This change affects both the workers and the flask application, so both would need to be redeployed.

Testing

I've tested this patch against a couple of playlists (no larger than a dozen videos) and files with large amounts of subtitles using multiple workers, and the lock seemed to work fine. You can confirm the lock is working from the frontend if you see tasks being held up by "Creating YoutubeDL instance".

Screenshot 2026-04-02 at 10 42 13 AM

In the screenshot the first task is downloading a video (with the lock), the second is transcoding one, and the third is waiting for the lock to be released. It's important to note that the lock doesn't prevent other encoding tasks from running as it's released the moment the YouTube API is no longer in use.

@Amdrel Amdrel requested a review from don-vip April 2, 2026 18:43
Comment on lines +39 to +47
RATE_LIMITED_DOMAINS = {
"youtube": {
"youtube.com",
"youtube-nocookie.com",
"youtubekids.com",
"youtu.be",
"youtube.googleapis.com",
},
}
Copy link
Copy Markdown
Collaborator Author

@Amdrel Amdrel Apr 2, 2026

Choose a reason for hiding this comment

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

I couldn't find a way to use the extractor since that appears to be determined after the params are created and sent to yt-dlp, so this is a bit of a hack. I'm open to replacing this if there's a better way.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

looks fine to me

@don-vip
Copy link
Copy Markdown
Collaborator

don-vip commented Apr 2, 2026

Nice! Let's see if it helps. At least it won't hurt :)

@don-vip don-vip merged commit 8755cde into master Apr 2, 2026
5 checks passed
@don-vip don-vip deleted the feat/download-rate-limiting branch April 2, 2026 21:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants