diff --git a/README.md b/README.md
index 5a0d918..6b28faf 100644
--- a/README.md
+++ b/README.md
@@ -4,28 +4,72 @@
[](https://github.com/cilium/workerpool/actions?query=workflow%3ATests)
[](https://goreportcard.com/report/github.com/cilium/workerpool)
-Package workerpool implements a concurrency limiting worker pool. Worker
-routines are spawned on demand as tasks are submitted; up to the configured
-limit of concurrent workers.
+**A concurrency-limiting worker pool for Go with backpressure and zero
+dependencies.**
-When the limit of concurrently running workers is reached, submitting a task
-blocks until a worker is able to pick it up. This behavior is intentional as it
-prevents from accumulating tasks which could grow unbounded. Therefore, it is
-the responsibility of the caller to queue up tasks if that's the intended
-behavior.
+Perfect for CPU-bound tasks that need controlled parallelism without
+unbounded queuing.
-One caveat is that while the number of concurrently running workers is limited,
-task results are not and they accumulate until they are collected. Therefore,
-if a large number of tasks can be expected, the workerpool should be
-periodically drained (e.g. every 10k tasks). Alternatively,
-`WithResultCallback` can be used to process results as they complete, avoiding
-accumulation entirely.
+## Features
-This package is mostly useful when tasks are CPU bound and spawning too many
-routines would be detrimental to performance. It features a straightforward API
-and no external dependencies. See the sections below for usage examples.
+- ✅ **Backpressure by design** - Blocks on submit when workers are busy
+ (no unbounded queues)
+- ✅ **On-demand workers** - Spawns workers as needed, up to configured
+ limit
+- ✅ **Two result modes** - Collect via `Drain()` or stream via callback
+- ✅ **Context-aware** - Full cancellation support for graceful shutdown
+- ✅ **Zero dependencies** - Pure standard library
+- ✅ **Simple API** - Submit, Drain, Close. That's it.
-## Example with Drain
+## Installation
+
+```bash
+go get github.com/cilium/workerpool
+```
+
+## Quick Start
+
+```go
+wp := workerpool.New(runtime.NumCPU())
+defer wp.Close()
+
+// Submit tasks (blocks when all workers are busy)
+err := wp.Submit("task-1", func(ctx context.Context) error {
+ // Your CPU-bound work here
+ return process(data)
+})
+
+// Collect results
+tasks, _ := wp.Drain()
+for _, task := range tasks {
+ if err := task.Err(); err != nil {
+ log.Printf("Task %s failed: %v", task, err)
+ }
+}
+```
+
+## When to Use This
+
+**Use workerpool when:**
+- Tasks are CPU-bound and need parallelism control
+- You want backpressure (block submission instead of queuing unbounded
+ tasks)
+- You need simple, predictable concurrency limiting
+
+**Don't use if:**
+- You need I/O-bound task handling (consider channels or goroutines
+ directly)
+- You want automatic retries, priorities, or complex scheduling
+- You need persistent job queues (use a proper job queue)
+
+## Usage Patterns
+
+### Pattern 1: Batch Processing with Drain
+
+Process tasks in batches and collect all results at once.
+
+
+Click to expand full example
```go
package main
@@ -111,13 +155,18 @@ func main() {
}
```
-## Example with result callback
+
+
+### Pattern 2: Streaming Results with Callback
-Use `WithResultCallback` to process each result as it completes rather than
-accumulating them for a later `Drain` call. The callback receives a `Result`,
-which extends `Task` with a `Duration()` method reporting how long the task
-took to execute. This is useful for logging, metrics, or long-running pools
-where unbounded result accumulation is undesirable.
+Use `WithResultCallback` to process each result as it completes rather
+than accumulating them for a later `Drain` call. The callback receives a
+`Result`, which extends `Task` with a `Duration()` method reporting how
+long the task took to execute. This is useful for logging, metrics, or
+long-running pools where unbounded result accumulation is undesirable.
+
+
+Click to expand full example
```go
package main
@@ -162,3 +211,25 @@ func main() {
}
}
```
+
+
+
+## Important Notes
+
+> [!WARNING]
+> **Result accumulation**: Without `WithResultCallback`, results accumulate
+> in memory until drained. For large workloads, drain periodically or use
+> the callback mode.
+
+> [!NOTE]
+> **Backpressure behavior**: `Submit()` blocks when no workers are
+> available. This is intentional to prevent unbounded queuing. Queue tasks
+> yourself if needed.
+
+> [!IMPORTANT]
+> **Cleanup**: Always `defer wp.Close()` to ensure graceful shutdown and
+> context cancellation.
+
+## Documentation
+
+Full API documentation: https://pkg.go.dev/github.com/cilium/workerpool