Pixtimize is an open source image transform API compatible with the ImageKit API. Pixtimize is compatible with any S3 bucket service.
This is a Rust rewrite built on Axum for a fast, memory-safe web server.
- Rust and Axum as the web framework and runtime
- AWS SDK for S3 to read source images and store transformed ones (any S3-compatible bucket)
- Redis to store the cached image keys
- libvips (via
libvips-rs) for fast, low-memory image decoding, resizing, and encoding
For every request the server:
- Parses the transform string (from the path or the
trquery param). - Computes a cache key:
sha256(image_path + transformations). - Looks up the transformed image in the cache. On a
GEThit the object is fetched from S3; on aHEADhit the body is never downloaded — Redis stores{s3_key, size, content_type}and S3HeadObjectis used only for legacy markers that lack size. - Otherwise it coalesces concurrent builds for the same cache key (in-process single-flight plus a Redis
SET NXlock across instances), fetches the source from S3, applies the transform, stores the result in S3, records metadata in Redis, and returns it.
When CACHE_DELETE_CRON is set, a cron job periodically clears the cache (Redis markers and the matching S3 objects). Omit the variable to disable cleanup.
| Property name | compatible | comment |
|---|---|---|
| w | ✅ | fixed pixel values, and fractions in (0, 1) are treated as a percentage |
| h | ✅ | fixed pixel values, and fractions in (0, 1) are treated as a percentage |
| q | ✅ | quality of the image, default value is DEFAULT_QUALITY |
| f | ✅ | output format, default is DEFAULT_FORMAT; values: jpeg, jpg, png, webp |
Aligned with ImageKit transformation limits (free-plan values where adjustable):
| Limit | Value | Behavior |
|---|---|---|
| Max image file size for processing | 20 MB | request rejected |
| Max image megapixels for processing | 25 MP | request rejected |
Max transform dimensions (w / h) |
65 535 px | larger absolute values are ignored |
| Max WebP transform / output dimensions | 16 383 px | request rejected |
You can transform an image by calling your URL like this (remember to encode the , as %2C in the query param):
https://yourdomain.com/image-example.png?tr=w-606,h-450,f-jpeg
or
https://yourdomain.com/tr:w-606,h-450,f-jpeg/image-example.png
Because Pixtimize speaks the ImageKit transform URL API, use it from the frontend with Unpic’s ImageKit provider — not a custom provider. Point Unpic at your Pixtimize base URL the same way you would point it at ImageKit.
See the Unpic ImageKit provider docs for options, operations (w, h, q, f, …), and other frameworks.
import { Image } from "@unpic/react";
export function ProductImage() {
return (
<Image
src="https://your-pixtimize-host/image-example.png"
width={800}
height={600}
alt="Example"
operations={{
imagekit: {
// imagekit operations here (supported transforms: see below)
},
}}
/>
);
}The generated URLs work against Pixtimize for the transforms this server implements (see Transforms compatibility).
Serve Pixtimize behind a CDN so transformed images are cached at the edge and delivered closer to users. Point the CDN origin at your Pixtimize host and use the CDN hostname in client URLs (including Unpic src).
We recommend LightCDN. Sign up with referral code gl6hwdgy.
Required environment variables:
S3_ENDPOINT: URL of the S3 bucket (defaulthttps://ams3.digitaloceanspaces.com)S3_BUCKET: name of the S3 bucketS3_ACCESS_KEY: access key id of the S3 bucketS3_SECRET_KEY: secret key of the S3 bucketREDIS_URL: Redis connection URL
Optional environment variables:
PORT: port to listen on (default3000)S3_REGION: S3 region (defaultams3)DEFAULT_QUALITY: default quality applied to optimize images (default80)DEFAULT_FORMAT: default output format (defaultwebp)CACHE_DELETE_CRON: optional cron schedule for cache cleanup (omit to disable). Example:0 1 * * 1(every Monday at 1am). Standard 5-field expressions are supported; a seconds field is optional.CACHED_TIME:max-age(in seconds) advertised on served images (default31536000, matching ImageKit’s 1-year CDN cache)
See .env.example for a template.
Image processing is powered by native libvips, so it must be installed before building or running locally:
# macOS
brew install vips
# Debian / Ubuntu
sudo apt-get install -y libvips-devOn Homebrew (or any non-standard prefix), point pkg-config at libvips so the build script can find it:
export PKG_CONFIG_PATH="$(brew --prefix vips)/lib/pkgconfig:$(brew --prefix)/lib/pkgconfig:$PKG_CONFIG_PATH"Install the toolchain from rustup.rs, then:
# run in development
cargo run
# run the tests
cargo test
# build an optimized release binary
cargo build --releasedocker build -t pixtimize .
docker run --rm -p 3000:3000 --env-file .env pixtimizeLicensed under the Apache License 2.0.
