An event-driven, high-performance image optimization microservice built with Bun and TypeScript.
The service listens for raw image upload events from MinIO / S3 via RabbitMQ, downloads the image to a localized temporary scratch space, processes and converts them to optimized WebP file using Bun’s native image APIs, and pushes them back onto the storage bucket.
Refer to docker-compose.yml image-optimizer section to see example docker compose usecase.
All environmental variables ending with
_FILE suffix are treated as secret (files) and supported.
Keep in mind that if both vars are defined it gets the regular one.
For example if you define MINIO_SECRET_KEY & MINIO_SECRET_KEY_FILE
it gets from MINIO_SECRET_KEY.
Outbound payload interface definition in optimized-event.types.ts
| Name | Required | Default | Description |
|---|---|---|---|
RABBITMQ_URL |
✅ Yes | None | AMQP broker connection string used to connect to your RabbitMQ cluster. |
MINIO_EVENT_EXCHANGE |
✅ Yes | None | RabbitMQ Exchange where MinIO publishes bucket notifications. |
MINIO_EVENT_ROUTING_KEY |
✅ Yes | None | The routing key (e.g., s3.ObjectCreated.*) used to bind the queue to the inbound exchange. |
OPTIMIZER_UPLOAD_QUEUE |
❌ No | "optimizer.image-uploads" |
Target RabbitMQ Queue that holds incoming image processing jobs. |
OPTIMIZER_EVENT_EXCHANGE |
❌ No | None | (Optional) Target RabbitMQ Exchange where successful image optimization event payloads are published. If omitted, outbound routing is disabled. |
OPTIMIZER_EVENT_ROUTING_KEY |
❌ No | None | (Optional) Routing key used when publishing completed optimization success events to the outbound exchange. |
MINIO_HOST |
❌ No | "localhost" |
Hostname or IP address of the MinIO S3 storage server. |
MINIO_PORT |
❌ No | 9000 |
Port used to connect to the MinIO API endpoint. |
MINIO_USE_SSL |
❌ No | "false" |
Toggles secure HTTPS/SSL transport connections (true / false). |
MINIO_ACCESS_KEY |
✅ Yes | None | Root access key or user ID credential for MinIO S3 authentication. |
MINIO_SECRET_KEY |
✅ Yes | None | Root secret token or password credential for MinIO S3 authentication. |
The worker relies on Amazon S3 Object Metadata headers to determine whether an image should be processed and how it should be transformed.
Processing and Filter Rules
-
Bypassing / Ignoring Files: If the any of required metadata headers is missing, the worker ignores the event entirely and leaves the object untouched.
-
Format Optimization: Regardless of the input format (JPEG, PNG, HEIC, etc.), the worker dynamically optimizes and converts the output exclusively into the WebP format using native
Bun.Imagebindings. -
Fallback Behavior: All optional fields omit execution overrides; if left out, they automatically defer to the optimized internal defaults provided by
Bun.Image.
| Name | Required | Default | Description |
|---|---|---|---|
X-Amz-Meta-Optimize-Image |
✅ Yes | None | Trigger flag for the worker. Must be exactly "true" to run the asset through the optimization pipeline. |
X-Amz-Meta-Quality |
✅ Yes | None | Target compression value. Must be a valid integer string between 1 and 100. |
X-Amz-Meta-Output-Object-Key |
✅ Yes | None | Destination S3 path where the final processed image will be written. |
X-Amz-Meta-Width |
❌ No | Bun.Image Default | Target resizing width in pixels. Must be a positive integer |
X-Amz-Meta-Height |
❌ No | Bun.Image Default | Target resizing height in pixels. Must be a positive integer |
X-Amz-Meta-Filter |
❌ No | Bun.Image Default | Resampling kernel algorithm used during scaling. Accepted values: nearest, box, bilinear, linear, cubic, mitchell, lanczos2, lanczos3, mks2013, mks2021. |
This project was created using bun init in bun v1.3.14. Bun is a fast all-in-one JavaScript runtime.
To install dependencies:
bun installCopy .env.example to .env and fill values. Also don't forget to create storage secret file in .docker/secrets/storage_secret_key.txt:
printf %s "password" > ./.docker/secrets/storage_secret_key.txtDon't forget to start docker compose before starting the app.
To start app:
bun dev🧪 To run tests:
bun test src/ # For unit tests
bun test tests/e2e # For e2e uploading tests