Ergonomic for a single backend
Read, write, stat, list, copy, and delete through one Operator, even when your application only uses S3 or a local directory. Paths, metadata, and error kinds follow one model across operations.
Write clean storage code from simple reads and writes to streaming, byte-range reads, and concurrent uploads — on a single S3 bucket or across 50+ backends.
use opendal::services::S3;
use opendal::Operator;
// Configure a backend once, then use one operator.
let builder = S3::default().bucket("data");
let op = Operator::new(builder)?;
op.write("hello.txt", "Hello, World!").await?;
let bytes = op.read("hello.txt").await?;
Adopt OpenDAL for one bucket or local directory today, then add large transfers, resilience policies, and more backends while your storage code keeps the same shape.
Read, write, stat, list, copy, and delete through one Operator, even when your application only uses S3 or a local directory. Paths, metadata, and error kinds follow one model across operations.
Stream large objects, read only the byte ranges you need, and upload parts concurrently on services with multipart or block writes. Add retries, timeouts, and concurrency limits as layers.
Use memory in tests, the local file system in development, and S3, GCS, Azure Blob, HDFS, or a database in production. Capability checks show where services differ.
One operator covers byte-range reads, concurrent transfers, file operations, and production policies. Examples use the Rust core; each language guide shows the options and layers its binding exposes.
let op = Operator::new(S3::default().bucket("data"))?;
// Read just the bytes you need.
let head = op.read_with("logs/today").range(0..64 * 1024).await?;
// Or read a large object in concurrent chunks.
let object = op
.read_with("big.parquet")
.concurrent(8)
.chunk(8 * 1024 * 1024)
.await?;
OpenDAL runs in production across the open-source ecosystem. These are some of the projects that build on it.
Enable only the backends your application needs. Core operations share one interface, and each service reports optional features through its capabilities.
Start with one bucket or directory, and keep the same operator model as your workloads and backends grow.