# How ReClip Handles Concurrent Downloads: Flask Threading and Subprocess Isolation

> Learn how ReClip handles concurrent downloads using Flask threading and subprocess isolation for parallel media downloads without blocking the server.

- Repository: [Avery Gan/reclip](https://github.com/averygan/reclip)
- Tags: internals
- Published: 2026-09-05

---

**ReClip achieves concurrent downloads by spawning a dedicated Python thread for each request that executes yt-dlp in an isolated subprocess, enabling parallel media downloads without blocking the Flask server's main request thread.**

ReClip is a lightweight Flask-based video downloader designed to handle multiple simultaneous downloads efficiently. When users submit URLs via the `/api/download` endpoint, the system leverages Python's **threading** module and subprocess isolation to process each download in the background. This architecture allows ReClip to handle concurrent downloads with minimal complexity while maintaining responsiveness.

## Thread-Per-Download Architecture

Each download request triggers a three-step initialization process defined in [`app.py`](https://github.com/averygan/reclip/blob/main/app.py). The server immediately returns a job identifier while delegating the blocking I/O operation to a background thread.

### Job ID Generation and State Initialization

When a client POSTs to `/api/download`, ReClip creates a unique 10-character hexadecimal job ID using Python's UUID module:

```python

# Located in /app.py#L77-L78

job_id = uuid.uuid4().hex[:10]

```

Immediately after generation, the server stores a job record in the global `jobs` dictionary with the status set to *downloading* and the request metadata preserved:

```python

# Located in /app.py#L78-L80

jobs[job_id] = {
    "status": "downloading",
    "url": url,
    "format": format_choice,
    # ... additional metadata

}

```

### Daemon Thread Execution

Rather than blocking the HTTP response while the download completes, ReClip delegates the work to a daemon thread. The server starts a new `threading.Thread` targeting the `run_download` function:

```python

# Located in /app.py#L180-L182

thread = threading.Thread(
    target=run_download,
    args=(job_id, url, format_choice, format_id)
)
thread.daemon = True
thread.start()

```

This approach returns the `job_id` to the client immediately, allowing the Flask request thread to handle additional HTTP traffic while the download proceeds in the background.

## Subprocess Isolation for Parallel Execution

The `run_download` function executes the actual media extraction using **yt-dlp** via `subprocess.run`. Because each thread invokes its own separate subprocess, multiple downloads operate truly in parallel without interfering with one another.

According to the averygan/reclip source code, the function executes the external command and blocks only within the daemon thread:

```python

# Conceptual implementation within run_download

subprocess.run(
    ["yt-dlp", "-f", format_id, "-o", output_path, url],
    check=True
)

```

This subprocess isolation ensures that CPU-intensive media processing does not stall the Flask application. The daemon thread monitors the subprocess completion and updates the global `jobs` dictionary with the final status, file path, or any error messages.

## Managing Shared State Without Locks

ReClip maintains download status through a global `jobs` dictionary that serves both the status endpoint (`/api/status/<job_id>`) and the file-serving endpoint (`/api/file/<job_id>`).

The implementation intentionally omits explicit locks because:

- **Write operations** are confined to the owning thread (only the thread that created the job modifies its entry)
- **Read operations** are read-only (status checks simply retrieve current state)

This design minimizes race conditions for small-scale deployments. When `run_download` completes, the thread updates the dictionary entry with `"status": "done"` and attaches the filename:

```python

# Executed by the background thread upon completion

jobs[job_id]["status"] = "done"
jobs[job_id]["filename"] = downloaded_file
jobs[job_id]["path"] = full_path

```

## Practical Example: Running Concurrent Downloads

You can initiate multiple downloads simultaneously using standard HTTP clients. Each request spawns an independent thread and subprocess:

```bash

# Start first download (video)

curl -X POST http://localhost:8899/api/download \
     -H "Content-Type: application/json" \
     -d '{"url":"https://youtu.be/abc123","format":"video"}'

```

```bash

# Start second download (audio) immediately

curl -X POST http://localhost:8899/api/download \
     -H "Content-Type: application/json" \
     -d '{"url":"https://youtu.be/def456","format":"audio"}'

```

Both downloads execute concurrently. Poll each job ID to track progress:

```bash
curl http://localhost:8899/api/status/<job_id> | jq .

```

Once the status returns `"done"`, retrieve the file:

```bash
curl -OJ http://localhost:8899/api/file/<job_id>

```

## Summary

- **Thread-per-request model**: Each `/api/download` invocation spawns a `threading.Thread` that runs independently of the Flask request handler, as implemented in `/app.py#L180-L182`.
- **Subprocess isolation**: The `run_download` function executes `yt-dlp` via `subprocess.run`, allowing the operating system to schedule multiple downloads simultaneously without blocking the server.
- **Lock-free state management**: The global `jobs` dictionary relies on thread-confinement (writes by owner only) rather than explicit synchronization primitives, minimizing race conditions for small-scale use.
- **Immediate job ID return**: Clients receive a unique identifier (generated via `uuid.uuid4().hex[:10]`) instantly and poll `/api/status/<job_id>` for completion.
- **Resource cleanup**: Daemon threads automatically clean up temporary files, leaving only the final chosen media file in the designated output directory.

## Frequently Asked Questions

### Does ReClip use async/await or an event loop for concurrent downloads?

No. As implemented in averygan/reclip, the project uses standard Python **threading** rather than `asyncio`. Each download runs in a dedicated `threading.Thread` that executes a blocking subprocess call. This design avoids the complexity of cooperative multitasking while achieving parallelism through operating system process scheduling.

### Is there a limit to how many simultaneous downloads ReClip can handle?

The repository does not enforce a hard limit on concurrent threads in the source code. However, practical limits depend on system resources (CPU, memory, network bandwidth) and available file descriptors. Since each download spawns both a Python thread and a separate `yt-dlp` process, resource exhaustion could occur under extreme load, though the lightweight Flask service is optimized for small to medium-scale deployments.

### How does ReClip prevent race conditions when updating download status?

The `jobs` dictionary avoids race conditions through architectural constraints rather than explicit locking. Writes to a specific job entry occur only within the single thread that owns that job (the daemon thread running `run_download`), while reads from the status endpoint are read-only operations. This thread-confinement pattern eliminates the need for mutex locks in this specific use case.

### What happens if a download subprocess fails?

When `subprocess.run` raises an exception or returns a non-zero exit code, the `run_download` thread catches the error and updates the corresponding `jobs` entry with `"status": "error"` and the error details. Clients polling `/api/status/<job_id>` receive the error state and can handle the failure appropriately without affecting other concurrent downloads.