<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>JuiceFS Blog</title><link>https://www.juicefs.com/en/blog/</link><description>Latest news from JuiceFS</description><atom:link href="http://juicefs.com/en/blog/latest/feed/" rel="self"/><language>en</language><lastBuildDate>Thu, 05 Nov 2026 08:56:00 +0000</lastBuildDate><item><title>How Horizon Robotics Uses JuiceFS for EB-Scale Autonomous Driving Data</title><link>https://www.juicefs.com/en/blog/user-stories/exabyte-scale-autonomous-driving-data</link><description>&lt;div class="w-block-markdown block-markdown"&gt;&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Horizon_Robotics"&gt;Horizon Robotics&lt;/a&gt; is a Chinese technology company that develops &lt;a href="https://en.wikipedia.org/wiki/Artificial_intelligence"&gt;artificial intelligence&lt;/a&gt; (AI) chips used in &lt;a href="https://en.wikipedia.org/wiki/Self-driving_car"&gt;self-driving&lt;/a&gt; cars and advanced driver assistance systems. We have partnered with 40+ original equipment manufacturers (OEMs) and brands globally and are the trusted choice for smart driving mass production among China's top 10 OEMs. &lt;/p&gt;
&lt;p&gt;Architecture is shaped by scale. At the exabyte level, with hundreds of billions of files, hundreds of thousands of clients, and 200 PB of data added and deleted every week, the assumptions built into open source file systems begin to break down.&lt;/p&gt;
&lt;p&gt;We use both &lt;a href="https://juicefs.com/docs/community/introduction/"&gt;JuiceFS Community Edition&lt;/a&gt; and &lt;a href="https://juicefs.com/docs/cloud/"&gt;Enterprise Edition&lt;/a&gt; to manage EB-scale data for our AIDI intelligent driving R&amp;amp;D platform. This article focuses on our experience with JuiceFS Community Edition, sharing how our team addressed four engineering challenges, the results we achieved, and the trade-offs we made.&lt;/p&gt;
&lt;h2&gt;New storage challenges at EB scale&lt;/h2&gt;
&lt;p&gt;AIDI supports our closed-loop intelligent driving R&amp;amp;D workflow. Data collected from road tests and production vehicles is filtered and labeled before entering &lt;a href="https://www.ibm.com/think/topics/model-training"&gt;model training&lt;/a&gt;. Trained models are evaluated and released, and data from newly identified issues feeds back into the pipeline. Storage underpins this entire workflow. &lt;strong&gt;How quickly data becomes available at each stage directly affects whether computing resources sit idle.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Over the past few years, the scale of this workflow has grown dramatically. &lt;strong&gt;Data capacity has increased from petabytes (PB) to exabytes (EB), while training capacity has grown from thousands to tens of thousands of GPUs&lt;/strong&gt;. As models iterate faster and data flows back into the pipeline more frequently, storage workloads have increasingly exceeded the assumptions behind the original architecture.&lt;/p&gt;
&lt;p&gt;Today, the platform faces the following scale and workload characteristics:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Capacity: EB scale (1018 bytes) and still growing, well beyond the scale covered by conventional JuiceFS Community Edition testing.  &lt;/li&gt;
&lt;li&gt;File count: Hundreds of billions (1011) of files. Individual directories, such as the trash, can contain tens of billions of entries.  &lt;/li&gt;
&lt;li&gt;Weekly data changes: Approximately 200 PB of data added and another 200 PB deleted, leaving tens of billions of objects to be deleted from object storage.  &lt;/li&gt;
&lt;li&gt;Client count: Hundreds of thousands of clients connecting through Kubernetes (K8s) training clusters, the Container Storage Interface (CSI), an S3-compatible gateway, and direct access through software development kits (SDKs).  &lt;/li&gt;
&lt;li&gt;Workload characteristics: Large sequential I/O for datasets coexists with small random I/O for training checkpoints. Access frequencies vary greatly between hot and cold data, and multiple tenants share a single metadata cluster.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These conditions led us to four engineering challenges:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;How can we prevent metadata hotspots and maintain stability with hundreds of billions of files?  &lt;/li&gt;
&lt;li&gt;How can we govern data safely and audibly when approximately 200 PB is deleted every week?  &lt;/li&gt;
&lt;li&gt;How can we balance training throughput and storage costs at EB scale?  &lt;/li&gt;
&lt;li&gt;How can we connect, rate-limit, and monitor hundreds of thousands of clients?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We began using JuiceFS Community Edition on AIDI in 2021 and have continuously customized it to address these challenges. As data volumes and use cases expanded, we gradually introduced JuiceFS Enterprise Edition as well. Both editions are now used on the platform. The sections below focus on our work with Community Edition and explain the changes we made and the trade-offs involved.&lt;/p&gt;
&lt;h2&gt;Challenge 1: Optimizing metadata for hundreds of billions of files&lt;/h2&gt;
&lt;h3&gt;Reducing metadata hotspots and large-directory pressure&lt;/h3&gt;
&lt;p&gt;Once the file count reached hundreds of billions, metadata access through &lt;a href="https://tikv.org/"&gt;TiKV&lt;/a&gt; exposed three bottlenecks:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;During peak training periods, the CPU on nodes hosting the leader replica was saturated, while follower replicas still had spare capacity.  &lt;/li&gt;
&lt;li&gt;Transactions requested global timestamps from the Timestamp Oracle (TSO) service in Placement Driver (PD), adding a network round trip.  &lt;/li&gt;
&lt;li&gt;Hot metadata, including mount configuration and capacity information, was queried repeatedly.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Further parameter tuning alone could no longer relieve these bottlenecks. We needed to change the access paths.&lt;/p&gt;
&lt;p&gt;To address them, we modified the Region routing cache in the TiKV Go client so follower replicas could handle read requests. We also eliminated one TSO round trip from frequent point lookups and introduced a read cache for hot metadata.&lt;/p&gt;
&lt;p&gt;We validated the changes against both old and new versions through continuous integration tests. Then, we delivered them as build-time patches, avoiding the need to maintain a long-lived fork of the upstream dependency. When scaling the cache cluster in or out, we also minimize large-scale cache-key remapping to reduce the risk of cache stampedes.&lt;/p&gt;&lt;/div&gt;
&lt;div class="w-block-ImageWithCaption block-ImageWithCaption"&gt;&lt;dl&gt;
    &lt;dt&gt;image&lt;/dt&gt;
    &lt;dd&gt;Metadata access paths&lt;/dd&gt;
    &lt;dt&gt;caption&lt;/dt&gt;
    &lt;dd&gt;Metadata access paths&lt;/dd&gt;
&lt;/dl&gt;&lt;/div&gt;
&lt;div class="w-block-markdown block-markdown"&gt;&lt;p&gt;Large directories containing billions of entries also put pressure on client memory. We adopted streaming, batched directory scans to avoid building the entire result set in memory during a single readdir call. This prevents out-of-memory failures and supports kernel-level readdir caching.&lt;/p&gt;
&lt;h3&gt;Rate limiting to keep the cluster stable&lt;/h3&gt;
&lt;p&gt;Hundreds of thousands of clients share one Meta cluster, and a single client can overwhelm it. &lt;strong&gt;To prevent one tenant's traffic from affecting the entire cluster, we independently limit resource consumption in the metadata and data planes.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;On the metadata side, we use token buckets based on PD Resource Groups. Request Units (RUs) measure and limit each tenant's resource consumption. In the data plane, we separately limit traffic to the cache cluster and traffic that falls back to object storage.&lt;/p&gt;
&lt;p&gt;Clients that exceed their budgets are throttled before their load can overwhelm shared resources. We manage rate-limit budgets declaratively: operators maintain the desired state in YAML files, and the manager compares that state with the current configuration and automatically generates SQL statements to create, alter, or delete database tables as needed.&lt;/p&gt;&lt;/div&gt;
&lt;div class="w-block-ImageWithCaption block-ImageWithCaption"&gt;&lt;dl&gt;
    &lt;dt&gt;image&lt;/dt&gt;
    &lt;dd&gt;Multi-tenant rate limiting and resource budgets&lt;/dd&gt;
    &lt;dt&gt;caption&lt;/dt&gt;
    &lt;dd&gt;Multi-tenant rate limiting and resource budgets&lt;/dd&gt;
&lt;/dl&gt;&lt;/div&gt;
&lt;div class="w-block-markdown block-markdown"&gt;&lt;h3&gt;Metadata disaster recovery: cold backups as a last line of defense&lt;/h3&gt;
&lt;p&gt;Metadata is critical to the entire system. TiKV stores the relationships between hundreds of billions of files and their metadata. If that metadata cannot be recovered, the file contents may still exist in object storage, but the system may no longer know which files they belong to.&lt;/p&gt;
&lt;p&gt;We use three layers of protection against different failure scenarios:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://tikv.org/docs/5.1/concepts/explore-tikv-features/replication-and-rebalancing/"&gt;TiKV Raft replication&lt;/a&gt; protects against hardware failures.  &lt;/li&gt;
&lt;li&gt;Periodic full snapshots of TiKV are backed up to object storage in a separate region. These backups provide a recovery path for accidentally deleted metadata in a keyspace, logical metadata corruption, and region-wide failures.  &lt;/li&gt;
&lt;li&gt;Object storage retains the file contents, allowing datasets to be used again after metadata recovery. When recovery is needed, we rebuild the TiKV cluster and restore the latest snapshot.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Cold backups come with a trade-off: metadata can only be restored to the most recent backup. Changes made afterward may be lost, and the potential recovery point depends on the backup interval. For our current training workloads, this is an acceptable trade-off.&lt;/p&gt;
&lt;h2&gt;Challenge 2: Data visibility and governance, reducing costs by deleting 200 PB every week&lt;/h2&gt;
&lt;p&gt;When approximately 200 PB of data is deleted each week, logical deletion is only the beginning. Object storage continues to accumulate billions of objects awaiting reclamation, and a single-node scan cannot keep up. Failed asynchronous deletions can also leave orphaned objects whose keys no longer reveal which files they belonged to.&lt;/p&gt;
&lt;p&gt;We built a governance workflow that connects deletion decisions, recovery from accidental deletion, space reclamation, and leak auditing.&lt;/p&gt;
&lt;h3&gt;Deletion decisions: dashboards and application-owner review&lt;/h3&gt;
&lt;p&gt;Application owners must decide what to delete and when. A trash cannot replace that decision-making process.&lt;/p&gt;
&lt;p&gt;We provide dashboards showing dataset access patterns, changes in access frequency, and capacity growth trends. Application owners use this information to plan deletions and capacity expansion. Once they confirm a decision, they can initiate deletion or recovery themselves. Deleted data first enters the trash.&lt;/p&gt;
&lt;p&gt;The dashboards rely on a metadata statistics pipeline that makes data queryable the next day (T+1). We first export the full set of file metadata from the Meta cluster to the data lakehouse to establish a baseline. After that, we synchronize incremental changes daily through the changelog.&lt;/p&gt;
&lt;p&gt;Application owners can query capacity, access patterns, and lifecycle data directly without asking the storage team to run queries for them. With approximately 200 PB of data added and deleted every week, any interruption or data drift in this pipeline can undermine capacity planning and reclamation decisions. Keeping the pipeline reliable is therefore essential.&lt;/p&gt;&lt;/div&gt;
&lt;div class="w-block-ImageWithCaption block-ImageWithCaption"&gt;&lt;dl&gt;
    &lt;dt&gt;image&lt;/dt&gt;
    &lt;dd&gt;Pipeline for exporting fine-grained statistics to the data lakehouse&lt;/dd&gt;
    &lt;dt&gt;caption&lt;/dt&gt;
    &lt;dd&gt;Pipeline for exporting fine-grained statistics to the data lakehouse&lt;/dd&gt;
&lt;/dl&gt;&lt;/div&gt;
&lt;div class="w-block-markdown block-markdown"&gt;&lt;h3&gt;Recovering deleted data: a seven-day trash&lt;/h3&gt;
&lt;p&gt;Data deleted through the platform remains in the trash for seven days. This window provides time to recover accidentally deleted data and absorbs the daily deletion volume, which can reach petabytes. It also prevents reclamation workloads from placing immediate pressure on the metadata engine.&lt;br&gt;
The trash uses different mechanisms for different paths:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style="text-align: left;"&gt;Mechanism&lt;/th&gt;
&lt;th style="text-align: left;"&gt;Design&lt;/th&gt;
&lt;th style="text-align: left;"&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;Paths that bypass the trash (mount options)&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Skip the trash for paths explicitly designated as non-recoverable, such as temporary training directories.&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Prevent large volumes of data from overwhelming the trash.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;Scheduled batch cleanup&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Delete data older than seven days in batches organized by time bucket. The process is observable and supports recovery.&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Manage trash capacity while preserving recovery capabilities.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;Streaming deletion lookup&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Scan deleted files as a stream to locate the requested data.&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Enable recovery within seconds and support deletion audits.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;During the retention period, application owners can restore data themselves through the recovery platform or command-line tools, without filing an operations ticket. Recovery rolls back metadata and rebuilds object references without copying the underlying data. The platform supports petabyte-scale daily recovery, and a single PB-scale recovery can finish within hours. Both deletion and recovery enforce permissions through access control lists (ACLs) and record audit logs.&lt;/p&gt;
&lt;h3&gt;Reclaiming space: distributed garbage collection&lt;/h3&gt;
&lt;p&gt;The standard Community Edition &lt;a href="https://en.wikipedia.org/wiki/Garbage_collection_computerscience"&gt;garbage collection&lt;/a&gt; (GC) relies on single-node scans. This cannot keep pace with approximately 200 PB of weekly deletions. We modified the process to record files and data slices awaiting deletion in TiKV, and then divide reclamation work into multiple shards for parallel processing by multiple workers.&lt;/p&gt;
&lt;p&gt;Workers acquire tasks through leases. After completing a task, a worker deletes its task record and claims the next batch. Tasks remain in TiKV until completion. If a worker fails, another worker can take over unfinished work. This approach distributes reclamation load without requiring a separate message queue.&lt;/p&gt;
&lt;p&gt;Leases determine which worker handles a task. Reference counts in the deletion transaction determine whether an object can actually be deleted. Physical deletion proceeds only when the reference count meets the deletion condition—in the current implementation, a negative value. This prevents concurrent processing or retries from causing duplicate deletions.&lt;/p&gt;
&lt;p&gt;On the object storage side, reclamation uses batch deletion, exponential backoff and retries, and audit records.&lt;/p&gt;
&lt;p&gt;We apply the same distributed processing model to large-file compaction. Files that grow through repeated appends can accumulate many slices, increasing read overhead. A separate &lt;code&gt;gc_cluster&lt;/code&gt; distributes compaction tasks from a manager to multiple workers.&lt;/p&gt;
&lt;p&gt;These workers periodically merge slices online to control read amplification.&lt;/p&gt;&lt;/div&gt;
&lt;div class="w-block-ImageWithCaption block-ImageWithCaption"&gt;&lt;dl&gt;
    &lt;dt&gt;image&lt;/dt&gt;
    &lt;dd&gt;Sharded gc_slices processing pipeline&lt;/dd&gt;
    &lt;dt&gt;caption&lt;/dt&gt;
    &lt;dd&gt;Sharded gc_slices processing pipeline&lt;/dd&gt;
&lt;/dl&gt;&lt;/div&gt;
&lt;div class="w-block-markdown block-markdown"&gt;&lt;h3&gt;Auditing orphaned objects with &lt;code&gt;leak-check&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;In addition to reclaiming objects based on metadata records, we use &lt;code&gt;leak-check&lt;/code&gt; to identify objects that were missed by the deletion process.&lt;/p&gt;
&lt;p&gt;The standard &lt;a href="https://juicefs.com/docs/cloud/reference/command_reference/#fsck"&gt;fsck&lt;/a&gt; check in JuiceFS looks for cases where metadata references an object that is missing. &lt;code&gt;leak-check&lt;/code&gt; performs the reverse check: it finds objects that still exist in storage but are no longer referenced by metadata.&lt;/p&gt;
&lt;p&gt;On the object storage side, we list objects concurrently across 32 subprefixes under &lt;code&gt;chunks/&lt;/code&gt;, reducing the bottleneck caused by scanning through a single connection. We independently obtain the object inventory and the metadata reference inventory. We then use two external-sort (&lt;code&gt;extsort&lt;/code&gt;) operations and merge the sorted results as streams to generate a candidate list. This avoids building a full in-memory map containing hundreds of billions of entries.&lt;/p&gt;&lt;/div&gt;
&lt;div class="w-block-ImageWithCaption block-ImageWithCaption"&gt;&lt;dl&gt;
    &lt;dt&gt;image&lt;/dt&gt;
    &lt;dd&gt;Dual-extsort merge in leak-check&lt;/dd&gt;
    &lt;dt&gt;caption&lt;/dt&gt;
    &lt;dd&gt;Dual-extsort merge in leak-check&lt;/dd&gt;
&lt;/dl&gt;&lt;/div&gt;
&lt;div class="w-block-markdown block-markdown"&gt;&lt;p&gt;The comparison results are only candidates for cleanup; they cannot be deleted immediately. Objects being written may temporarily lack metadata references. By default, the audit generates a list without deleting anything and filters out recently created objects. Deletion happens only after the candidates are reviewed and confirmed. This process helps find orphaned objects while reducing the risk of deleting writes that are still in progress.&lt;/p&gt;
&lt;h2&gt;Challenge 3: Balancing training performance and EB-scale storage costs&lt;/h2&gt;
&lt;p&gt;Training requires throughput on the order of hundreds of GB/s. It also combines large sequential I/O for datasets with small random I/O for checkpoints. At EB scale, we cannot keep all data in the hot tier. When compute runs across multiple clouds, data must also be accessible from locations close to the workloads.&lt;/p&gt;
&lt;h3&gt;Three-tier caching: from clients to a centralized cluster&lt;/h3&gt;
&lt;p&gt;Our three-tier cache expands the sharing scope at each level:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;L1 cache: Reuses data blocks within the current client.  &lt;/li&gt;
&lt;li&gt;L2 cache: Shares data blocks between clients through peer-to-peer (P2P) transfers.  &lt;/li&gt;
&lt;li&gt;L3 cache: A centralized cluster that serves hot training data for both reads and writes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Reads check L1, L2, and L3 in sequence. Only when all three tiers miss does the client access object storage.&lt;br&gt;
When multiple training jobs read the same dataset, L1 caching alone cannot share data across clients, so clients may fetch the same data from object storage repeatedly. L2 allows clients to act as cache peers. A block already cached by one client can be reused by another through the range-read (&lt;code&gt;getrange&lt;/code&gt;) interface. When dozens of jobs read the same data concurrently, the total amount fetched from object storage can approach the size of a single copy. This saves bandwidth by making better use of existing local disks and memory.&lt;br&gt;
Requests that miss both L1 and L2 proceed to the centralized L3 cache cluster, which handles PB-scale data. L3 serves hot working sets shared across clients and absorbs most of the read throughput. The same cluster provides both read caching and write aggregation: read caching serves large sequential dataset I/O, while write aggregation handles small random checkpoint I/O. The cluster can scale horizontally to increase hot-data capacity.&lt;br&gt;
A cache failure could force hundreds of thousands of clients to fetch data directly from object storage at once, increasing the load on the storage backend. We use health checks to remove unhealthy nodes and reintroduce them after recovery. If the read cache becomes entirely unavailable, clients fall back to direct reads from object storage, trading higher latency for continued access.&lt;br&gt;
We also record cache hit counts, bytes served, latency, and slow requests at each tier. These metrics help us detect cache degradation and changes in fallback traffic.&lt;/p&gt;
&lt;h3&gt;Metadata caching: avoiding repeated lookups&lt;/h3&gt;
&lt;p&gt;When a training job reads a file, it must do more than retrieve data blocks. It also repeatedly looks up files, retrieves file attributes, and opens files through operations such as lookup, getattr, and open. Each operation requires a metadata query.&lt;br&gt;
To reduce repeated requests to TiKV, the client uses an &lt;a href="https://juicefs.com/docs/community/command_reference#mount-metadata-cache-options"&gt;open cache&lt;/a&gt; to retain query results.&lt;br&gt;
The challenge is that different file types change at different rates. Dataset images and packaged files usually remain unchanged for long periods and can be cached longer. Indexes and logs, by contrast, may change continuously and need to reflect updates quickly.&lt;/p&gt;
&lt;p&gt;Using the same time-to-live (TTL) for every file creates a trade-off: a long TTL risks serving stale metadata, while a short TTL forces frequently accessed but unchanged files to query the backend repeatedly.&lt;br&gt;
Therefore, we define three TTL tiers by file type. Static files use longer TTLs, dynamic files use TTLs measured in seconds, and other files use the default TTL. The configuration supports hot reloading through YAML.&lt;br&gt;
For static files, a cache hit renews the lease (&lt;code&gt;expire_lease&lt;/code&gt;), resetting the expiration time. Frequently used files can therefore remain cached, while cold files expire naturally. The modification-time filter (&lt;code&gt;filter_mtime&lt;/code&gt;) prevents recently modified files—which may still be receiving writes—from entering the cache. This avoids caching metadata before it has stabilized.&lt;/p&gt;&lt;/div&gt;
&lt;div class="w-block-ImageWithCaption block-ImageWithCaption"&gt;&lt;dl&gt;
    &lt;dt&gt;image&lt;/dt&gt;
    &lt;dd&gt;File-type-based metadata caching policies&lt;/dd&gt;
    &lt;dt&gt;caption&lt;/dt&gt;
    &lt;dd&gt;File-type-based metadata caching policies&lt;/dd&gt;
&lt;/dl&gt;&lt;/div&gt;
&lt;div class="w-block-markdown block-markdown"&gt;&lt;h3&gt;Controlling read amplification: coordinating prefetching and caching&lt;/h3&gt;
&lt;p&gt;Prefetching can accelerate sequential reads, but excessive prefetching can also increase load on the storage backend. &lt;strong&gt;We control prefetching independently at the cache layer and the kernel layer.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;At the cache layer, the client uses block sequence numbers in object keys to fetch subsequent blocks in advance.&lt;/strong&gt; A deduplication table and bounded queue limit concurrency. When the queue is full, the client drops prefetch requests rather than blocking normal reads.&lt;br&gt;
At the kernel layer, dynamic read-ahead adjusts the window based on whether access is sequential or random. A global watermark limits the overall load, and the configuration supports hot reloading.&lt;/p&gt;&lt;/div&gt;
&lt;div class="w-block-ImageWithCaption block-ImageWithCaption"&gt;&lt;dl&gt;
    &lt;dt&gt;image&lt;/dt&gt;
    &lt;dd&gt;Two-stage prefetch pipeline&lt;/dd&gt;
    &lt;dt&gt;caption&lt;/dt&gt;
    &lt;dd&gt;Two-stage prefetch pipeline&lt;/dd&gt;
&lt;/dl&gt;&lt;/div&gt;
&lt;div class="w-block-markdown block-markdown"&gt;&lt;h3&gt;Keeping data close to compute and tiering by access frequency&lt;/h3&gt;
&lt;p&gt;The changes described above improve access to hot data. Controlling storage costs at EB scale also requires deciding where data should reside.  &lt;/p&gt;
&lt;p&gt;When training workloads run across multiple clouds, we allow buckets in different regions to share a single file-system namespace. Metadata records each object's owning bucket and storage tier. Read requests use this information to route to the appropriate bucket, so migrating data does not require application access paths to change.  &lt;/p&gt;
&lt;p&gt;Data moves directly between buckets on the server side, without consuming client bandwidth. During migration, the read path falls back across the hot tier, cold tier, and full pool as needed. Declarative configuration controls the owning bucket and migration policy for datasets or directories.  &lt;/p&gt;
&lt;p&gt;When training compute moves to another cloud, we can migrate data to the corresponding region in advance, reducing dependence on cross-cloud dedicated bandwidth. Infrequently accessed data can be moved to lower-cost buckets or cold-storage pools such as tape libraries and retrieved when needed.  &lt;/p&gt;
&lt;p&gt;This approach keeps hot data close to compute while controlling storage costs at EB scale. Capacity scaling no longer depends on a single cloud provider. Critical datasets can also retain backup buckets in other clouds, providing an alternative read path during cloud outages.&lt;/p&gt;&lt;/div&gt;
&lt;div class="w-block-ImageWithCaption block-ImageWithCaption"&gt;&lt;dl&gt;
    &lt;dt&gt;image&lt;/dt&gt;
    &lt;dd&gt;Architecture for data locality and hot:cold tiering&lt;/dd&gt;
    &lt;dt&gt;caption&lt;/dt&gt;
    &lt;dd&gt;Architecture for data locality and hot/cold tiering&lt;/dd&gt;
&lt;/dl&gt;&lt;/div&gt;
&lt;div class="w-block-markdown block-markdown"&gt;&lt;h2&gt;Challenge 4: Connecting and managing hundreds of thousands of clients&lt;/h2&gt;
&lt;p&gt;When hundreds of thousands of clients connect simultaneously, multi-tenant access control, connection methods, and client observability all need to be designed for scale. We address these concerns through access control, training-job integration, and client monitoring.&lt;/p&gt;
&lt;h3&gt;Multi-tenancy: access control&lt;/h3&gt;
&lt;p&gt;Our production kernel versions do not support enabling &lt;a href="https://en.wikipedia.org/wiki/POSIX"&gt;POSIX&lt;/a&gt;-compliant ACLs on the Filesystem in Userspace (FUSE) mount path. Therefore, we moved tenant authorization into a user-space ACL Manager.  &lt;/p&gt;
&lt;p&gt;The ACL Manager uses buckets as the unit of authorization and manages permissions through the READER and MAINTAINER role groups. It supplements lightweight directory access protocol (LDAP) group information using globally unique identifier (GUID) files and records audit logs.&lt;/p&gt;&lt;/div&gt;
&lt;div class="w-block-ImageWithCaption block-ImageWithCaption"&gt;&lt;dl&gt;
    &lt;dt&gt;image&lt;/dt&gt;
    &lt;dd&gt;ACL Manager&lt;/dd&gt;
    &lt;dt&gt;caption&lt;/dt&gt;
    &lt;dd&gt;ACL Manager&lt;/dd&gt;
&lt;/dl&gt;&lt;/div&gt;
&lt;div class="w-block-markdown block-markdown"&gt;&lt;p&gt;With this design, LDAP only needs to maintain group membership. The ACL Manager implements ACL semantics in user space, bypassing kernel-version limitations and rejecting unauthorized access to shared file systems during authorization.&lt;br&gt;
&lt;strong&gt;The trade-off is additional user-space authorization overhead&lt;/strong&gt;, which we mitigate with a three-level inode cache.&lt;/p&gt;
&lt;h3&gt;Access methods: S3 Gateway and a mountless SDK&lt;/h3&gt;
&lt;p&gt;In addition to POSIX mounts, we provide two access paths: an S3 Gateway built on the MinIO plugin layer and an in-process SDK for direct data access.  &lt;/p&gt;
&lt;p&gt;Some applications already use the S3 protocol and need to keep their existing interfaces while accessing the same data. The S3 Gateway translates object-protocol requests into file-system operations. It shares the same file-system namespace with POSIX mounts and the SDK, reusing the same permissions, caches, and underlying data.  &lt;/p&gt;
&lt;p&gt;The plugin layer implements directory-level tenant isolation and user-token validation, and fixes slow paginated queries in ListObjectsV2. We also removed support for non-S3 backends to create a lightweight image. For cross-cloud dedicated-network scenarios, we provide a lightweight SDK for read-side access via the S3 protocol.  &lt;/p&gt;
&lt;p&gt;The other access path targets highly concurrent training workloads. As the number of jobs and dataloader processes grows, the number of simultaneously active client data connections can reach the millions. FUSE access requires requests to pass through the kernel, while short-lived jobs repeatedly mount and unmount the file system. The resulting connection and mount overhead accumulates.  &lt;/p&gt;
&lt;p&gt;To address this, we developed an in-process Python SDK that reads data directly without requiring a mount. Connections are created and exit with the process. The trade-off is that the SDK must manage process connections, sessions after &lt;code&gt;fork&lt;/code&gt;, and heartbeats itself.  &lt;/p&gt;
&lt;p&gt;The SDK starts with the container and integrates with existing data-loading pipelines through &lt;code&gt;fsspec&lt;/code&gt; and &lt;code&gt;ffrecord&lt;/code&gt;. When dataloader processes are forked, each child process recreates its session and heartbeat thread and reports metrics independently. During operation, the SDK periodically reports metrics and receives heartbeat intervals and rate-limit policies from the server.  &lt;/p&gt;
&lt;p&gt;Training workloads use read-only access, and write operations are blocked at multiple layers. Path validation and cross-bucket isolation further prevent unauthorized access.&lt;/p&gt;&lt;/div&gt;
&lt;div class="w-block-ImageWithCaption block-ImageWithCaption"&gt;&lt;dl&gt;
    &lt;dt&gt;image&lt;/dt&gt;
    &lt;dd&gt;Mountless direct-read architecture for the Python SDK&lt;/dd&gt;
    &lt;dt&gt;caption&lt;/dt&gt;
    &lt;dd&gt;Mountless direct-read architecture for the Python SDK&lt;/dd&gt;
&lt;/dl&gt;&lt;/div&gt;
&lt;div class="w-block-markdown block-markdown"&gt;&lt;h3&gt;Metric observability and client upgrades&lt;/h3&gt;
&lt;p&gt;Each of hundreds of thousands of clients can generate hundreds of metrics. If Prometheus scraped every client individually, the number of time series would grow rapidly.  &lt;/p&gt;
&lt;p&gt;Instead, clients report metrics to &lt;code&gt;MetricManager&lt;/code&gt; in shards, and Prometheus scrapes the aggregated results. &lt;code&gt;MetricManager&lt;/code&gt; controls time-series cardinality by merging or dropping some fine-grained labels. &lt;strong&gt;The trade-off is that some observability dimensions are no longer available.&lt;/strong&gt;  &lt;/p&gt;
&lt;p&gt;The aggregation service must also support hot configuration updates, recovery from failures, dropping data under overload, and expiration-based cleanup. Otherwise, the service itself could become a bottleneck.  &lt;/p&gt;
&lt;p&gt;Rolling out upgrades across hundreds of thousands of clients must also minimize disruption to training workloads. The Gateway and file-system client (FS) images are produced through the same build pipeline. Combined with stateless clients and rolling restarts in K8s, this supports staged upgrades.  &lt;/p&gt;
&lt;p&gt;Upgrades to the direct-read SDK and S3 Gateway are transparent to training jobs. For POSIX mounts, the disruption window can be kept under control.  &lt;/p&gt;
&lt;p&gt;We are evaluating several general-purpose improvements for potential upstream contributions, including batched cache APIs, streaming scans through &lt;code&gt;ReaddirFrom&lt;/code&gt;, and dynamic read-ahead. Features more tightly coupled to our application requirements, such as ACLs and the end-to-end data governance workflow, will continue to evolve internally.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Our experience managing EB-scale capacity, hundreds of billions of files, and hundreds of thousands of clients comes down to four principles.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Distribute the workload to eliminate centralized bottlenecks.&lt;/strong&gt; We distribute metadata reads across follower replicas, eliminate the extra TSO round trip for frequent point lookups, and optimize hot keys to prevent individual nodes from becoming overloaded. We also customize the metadata access path to improve overall performance. When designing the architecture, we must account for the impact of failures in components that carry global workloads.  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Govern the data lifecycle with an end-to-end workflow.&lt;/strong&gt; Dashboards support deletion decisions by application owners; a seven-day trash and PB-scale recovery protect against accidental deletion; GC reclaims space; and &lt;code&gt;leak-check&lt;/code&gt; audits orphaned objects. Recovery throughput must keep pace with deletion volume so that reclamation anomalies remain within an acceptable space-reclamation delay, reducing both accidental data loss and the risk of permanent storage leaks.  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Protect training performance through tiered caching and bounded prefetching.&lt;/strong&gt; L1 client caching, L2 P2P caching between clients, and the centralized L3 cluster absorb load at progressively broader sharing scopes. Prefetching is constrained by global limits and queue watermarks. When queues fill, requests are dropped rather than allowed to slow normal reads through additional read amplification. Data locality and hot/cold tiering further reduce cross-cloud access costs and EB-scale storage expenses.  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Limit the impact of individual tenants through access control and resource budgets.&lt;/strong&gt; ACLs define the scope of access, while token buckets constrain each tenant's resource consumption in both the metadata and data planes. Declarative RU-based resource budgets make these limits manageable and help prevent a single client from destabilizing the shared cluster.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As data volumes, compute capacity, and application complexity continue to grow, we’ll keep improving the metadata engine, data plane, performance engineering, governance mechanisms, and observability. Our goal is to prepare the architecture for the next order-of-magnitude increase before it arrives. Identifying potential bottlenecks early and addressing them proactively will remain a central focus of our work.&lt;/p&gt;
&lt;p&gt;If you have any feedback on this article or ideas to share, we invite you to participate in the &lt;a href="https://github.com/juicedata/juicefs/discussions/"&gt;discussions on GitHub&lt;/a&gt; and join &lt;a href="http://go.juicefs.com/discord"&gt;our community on Discord&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;</description><pubDate>Thu, 05 Nov 2026 08:56:00 +0000</pubDate><guid>https://www.juicefs.com/en/blog/user-stories/exabyte-scale-autonomous-driving-data</guid></item><item><title>How Zhuoyu Built a Petabyte-Scale Data Platform for Autonomous Driving with JuiceFS</title><link>https://www.juicefs.com/en/blog/user-stories/build-petabyte-scale-data-platform-self-driving-with-juicefs</link><description>&lt;div class="w-block-markdown block-markdown"&gt;&lt;p&gt;Founded in 2016, &lt;a href="https://www.zyt.com/en/about"&gt;Zhuoyu Technology&lt;/a&gt; (ZYT) focuses on the research, development, and large-scale application of mobile intelligence technologies. Leveraging our proprietary native multimodal foundation models and generative AI technologies, we build a unified mobile intelligence technology base that can efficiently adapt to multiple scenarios. It not only provides automakers with open, customizable, production-oriented intelligent driving assistance solutions (covering L2 and above), but also delivers underlying technology for autonomous mobile robots in diverse scenarios, empowering a full-spectrum intelligent mobility ecosystem from the ground to near-space.&lt;/p&gt;
&lt;p&gt;As R&amp;amp;D scale expands, training and inference compute are gradually moving toward multi-data-center and &lt;a href="https://www.ibm.com/think/topics/hybrid-cloud"&gt;hybrid-cloud&lt;/a&gt; environments, while data volume and access demands continue to grow. Compute resources can be scheduled on demand, but task startup can still be affected by mount status, origin data fetches, and model loading. &lt;strong&gt;How to make data ready in time and reduce compute waiting has become a key goal of storage architecture evolution.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;We built a unified data foundation on &lt;a href="https://juicefs.com/docs/community/introduction/"&gt;JuiceFS&lt;/a&gt;. Through unified access, multiple storage pools, and shared caching, it supports data ingestion, capacity scaling, and hot data reuse. Combined with proactive warm-up and read optimization, it accelerates data delivery. Today, the online cluster carries 100-PB-scale data, with online read capability reaching the 100 GB/s range. This article covers the architecture evolution and production practices.&lt;/p&gt;
&lt;h2&gt;The autonomous driving data loop: growing volumes and repeated data consumption&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Self-driving_car"&gt;Autonomous driving&lt;/a&gt; R&amp;amp;D revolves around a continuous data loop. Data collected by road-testing and production vehicles is filtered and labeled before entering model training. The resulting models then go through evaluation and deployment, while newly identified issues and newly collected data feed into the next iteration. At each stage, how quickly data becomes available directly affects whether compute resources have to wait and, ultimately, how efficiently R&amp;amp;D teams can iterate.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;From a storage perspective, autonomous driving R&amp;amp;D is a data-intensive pipeline.&lt;/strong&gt; Multimodal data continuously flows back into the platform and is repeatedly consumed by different R&amp;amp;D workloads. Data collected by production and road-testing vehicles, together with simulation-generated data, first enters shared multimodal storage. Downstream workloads—including data filtering, labeling, model training, simulation evaluation, and individual development environments—then consume the data.&lt;/p&gt;&lt;/div&gt;
&lt;div class="w-block-ImageWithCaption block-ImageWithCaption"&gt;&lt;dl&gt;
    &lt;dt&gt;image&lt;/dt&gt;
    &lt;dd&gt;Multimodal data flow R&amp;amp;D&lt;/dd&gt;
    &lt;dt&gt;caption&lt;/dt&gt;
    &lt;dd&gt;Multimodal data flow and consumption in autonomous driving R&amp;amp;D&lt;/dd&gt;
&lt;/dl&gt;&lt;/div&gt;
&lt;div class="w-block-markdown block-markdown"&gt;&lt;p&gt;As data volumes and iteration frequency increase, storage must support both continuous capacity growth and efficient data access to keep downstream workloads supplied with data.&lt;/p&gt;
&lt;h2&gt;Coupling between access, operations, and scaling in the original architecture&lt;/h2&gt;
&lt;p&gt;Before adopting JuiceFS, we used both S3 APIs and file-based access. Multiple access paths coexisted, storage configuration was scattered across applications, and compute-side teams were responsible for maintaining mount clients.&lt;/p&gt;&lt;/div&gt;
&lt;div class="w-block-ImageWithCaption block-ImageWithCaption"&gt;&lt;dl&gt;
    &lt;dt&gt;image&lt;/dt&gt;
    &lt;dd&gt;Multiple storage access paths and distributed configuration&lt;/dd&gt;
    &lt;dt&gt;caption&lt;/dt&gt;
    &lt;dd&gt;Multiple storage access paths and distributed configuration before the migration&lt;/dd&gt;
&lt;/dl&gt;&lt;/div&gt;
&lt;div class="w-block-markdown block-markdown"&gt;&lt;p&gt;We identified three core challenges:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Mounting coupled with workload scheduling:&lt;/strong&gt; Task startup depended on mount clients being ready. Maintaining those clients on the compute side increased operational overhead and could leave compute resources waiting for storage.  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Storage configuration coupled with applications:&lt;/strong&gt; Storage details such as buckets, endpoints, and credentials were embedded in application code. Changes to underlying storage resources required application-side changes.  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Capacity coupled with bandwidth scaling:&lt;/strong&gt; Data volumes continued to grow while workloads repeatedly accessed hotspot data. Local caches could not be reused across nodes, making it difficult to scale storage capacity and read bandwidth independently.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Therefore, the new architecture needed to simplify application integration and mount management while allowing storage capacity and read bandwidth to scale independently.&lt;/p&gt;
&lt;h2&gt;Architecture upgrade: building a unified data platform on JuiceFS&lt;/h2&gt;
&lt;h3&gt;Technology selection: S3 as the primary interface, JuiceFS as the storage foundation&lt;/h3&gt;
&lt;p&gt;To maintain compatibility with existing workloads while supporting future growth, we chose JuiceFS as the storage foundation for four main reasons:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Multiple &lt;a href="https://juicefs.com/docs/community/introduction/#features"&gt;access protocols&lt;/a&gt;:&lt;/strong&gt; JuiceFS supports interfaces such as S3 and POSIX, allowing different workloads to use the access method that best fits their needs.  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Capacity scaling:&lt;/strong&gt; JuiceFS uses object storage as the underlying data store, providing room for continued data growth.  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cache acceleration:&lt;/strong&gt; The &lt;a href="https://juicefs.com/docs/community/introduction/"&gt;Community Edition&lt;/a&gt; already provides local caching, giving us a foundation for further read-path optimizations.  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Open source ecosystem:&lt;/strong&gt; An active community makes it easier to continue improving the platform based on production requirements.&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;
&lt;div class="w-block-ImageWithCaption block-ImageWithCaption"&gt;&lt;dl&gt;
    &lt;dt&gt;image&lt;/dt&gt;
    &lt;dd&gt;1JuiceFS 架构图.drawio&lt;/dd&gt;
    &lt;dt&gt;caption&lt;/dt&gt;
    &lt;dd&gt;JuiceFS Community Edition architecture&lt;/dd&gt;
&lt;/dl&gt;&lt;/div&gt;
&lt;div class="w-block-markdown block-markdown"&gt;&lt;h3&gt;Unified access layer: decoupling applications from storage&lt;/h3&gt;
&lt;p&gt;In the new architecture, applications access storage through an SDK provided by our internal data platform. The SDK provides a unified logical namespace and handles the mapping between logical paths and underlying storage locations and credentials. Applications integrated through the SDK primarily use S3 access, reducing the need to manage mount clients on compute nodes. Existing workloads can continue to use the &lt;a href="https://en.wikipedia.org/wiki/POSIX"&gt;POSIX&lt;/a&gt; interface.&lt;/p&gt;&lt;/div&gt;
&lt;div class="w-block-ImageWithCaption block-ImageWithCaption"&gt;&lt;dl&gt;
    &lt;dt&gt;image&lt;/dt&gt;
    &lt;dd&gt;Unified access layer and logical namespace based on the SDK&lt;/dd&gt;
    &lt;dt&gt;caption&lt;/dt&gt;
    &lt;dd&gt;Unified access layer and logical namespace based on the SDK&lt;/dd&gt;
&lt;/dl&gt;&lt;/div&gt;
&lt;div class="w-block-markdown block-markdown"&gt;&lt;p&gt;Using S3 as the primary access path also makes it easier to implement traffic isolation, monitoring, and auditing at the access layer.&lt;/p&gt;
&lt;p&gt;The unified access layer separates application changes from storage changes, reducing the impact of underlying resource changes on application integration. We can continue scaling capacity, adding caches, and integrating external data sources while keeping the interfaces exposed to applications stable.&lt;/p&gt;
&lt;h2&gt;Building the core capabilities&lt;/h2&gt;
&lt;p&gt;We extended the JuiceFS Community Edition with multiple storage pools, distributed caching, and Under File System (UFS). The resulting architecture is shown below.&lt;/p&gt;&lt;/div&gt;
&lt;div class="w-block-ImageWithCaption block-ImageWithCaption"&gt;&lt;dl&gt;
    &lt;dt&gt;image&lt;/dt&gt;
    &lt;dd&gt;multiple storage pools, distributed caching, and UFS&lt;/dd&gt;
    &lt;dt&gt;caption&lt;/dt&gt;
    &lt;dd&gt;Architecture integrating multiple storage pools, distributed caching, and UFS&lt;/dd&gt;
&lt;/dl&gt;&lt;/div&gt;
&lt;div class="w-block-markdown block-markdown"&gt;&lt;h3&gt;Multiple storage pools: scaling capacity and isolating failures&lt;/h3&gt;
&lt;p&gt;We added routing to the data layer of a JuiceFS volume. Based on policies such as file size and configured weights, the router distributes writes across different storage pools. The backends can be multiple S3 buckets or file storage systems.&lt;/p&gt;&lt;/div&gt;
&lt;div class="w-block-ImageWithCaption block-ImageWithCaption"&gt;&lt;dl&gt;
    &lt;dt&gt;image&lt;/dt&gt;
    &lt;dd&gt;multiple storage pools in a single volume&lt;/dd&gt;
    &lt;dt&gt;caption&lt;/dt&gt;
    &lt;dd&gt;Write routing and capacity scaling across multiple storage pools in a single volume&lt;/dd&gt;
&lt;/dl&gt;&lt;/div&gt;
&lt;div class="w-block-markdown block-markdown"&gt;&lt;p&gt;&lt;strong&gt;This gives us a one-to-many relationship between a JuiceFS volume and its underlying buckets. When an object storage resource reaches its scaling limit, we can add another storage pool to handle subsequent writes without migrating the existing data as a whole.&lt;/strong&gt; Multiple independent storage pools also help reduce the impact of failures within any single resource domain.&lt;/p&gt;
&lt;h3&gt;Distributed caching: reusing hot data across nodes&lt;/h3&gt;
&lt;p&gt;Initially, we used local caching, which prevented nodes from sharing cached data. When a workload was scheduled to a new node and the required data was not available locally, the node had to fetch the data from the source again and keep another copy in its local cache. This increased read latency and reduced cache utilization.&lt;/p&gt;
&lt;p&gt;To address this, we developed &lt;a href="https://en.wikipedia.org/wiki/Distributed_cache"&gt;distributed caching&lt;/a&gt; of the Community Edition. Multiple clients can reuse hot data in a shared cache, while object storage remains the authoritative source of data. The read path works as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The client uses consistent hashing to select a cache node.  &lt;/li&gt;
&lt;li&gt;If the data is available on the cache node's local disk, the node returns it directly.  &lt;/li&gt;
&lt;li&gt;If the data is not cached and fetching from the source is allowed, the cache node reads it from S3, returns the data to the client, and keeps a copy locally.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Local client-side caching remains available, giving us a multi-level caching architecture together with distributed caching.&lt;/p&gt;&lt;/div&gt;
&lt;div class="w-block-ImageWithCaption block-ImageWithCaption"&gt;&lt;dl&gt;
    &lt;dt&gt;image&lt;/dt&gt;
    &lt;dd&gt;Distributed cache read path&lt;/dd&gt;
    &lt;dt&gt;caption&lt;/dt&gt;
    &lt;dd&gt;Distributed cache read path&lt;/dd&gt;
&lt;/dl&gt;&lt;/div&gt;
&lt;div class="w-block-markdown block-markdown"&gt;&lt;h3&gt;UFS: integrating external data and accelerating access&lt;/h3&gt;
&lt;p&gt;We also developed UFS of the Community Edition to bring external data sources into the JuiceFS namespace. UFS provides unified access to external data and accelerates reads through caching, while the authoritative copy remains in the original system.&lt;/p&gt;
&lt;p&gt;For example, suppose an existing dataset is stored in S3 and we want to accelerate access using the JuiceFS cache. We can map the dataset to a path in JuiceFS without migrating the original data. Then, applications can access the data through the mapped path.&lt;/p&gt;&lt;/div&gt;
&lt;div class="w-block-ImageWithCaption block-ImageWithCaption"&gt;&lt;dl&gt;
    &lt;dt&gt;image&lt;/dt&gt;
    &lt;dd&gt;unified namespace with UFS&lt;/dd&gt;
    &lt;dt&gt;caption&lt;/dt&gt;
    &lt;dd&gt;Mapping external data sources into a unified namespace with UFS&lt;/dd&gt;
&lt;/dl&gt;&lt;/div&gt;
&lt;div class="w-block-markdown block-markdown"&gt;&lt;p&gt;The current implementation uses read-only mappings. It supports the same backend storage types as the Community Edition. Metadata can be loaded on demand or warmed up in advance. Even without warm-up, JuiceFS can retrieve directory and file metadata from the external storage as needed when a directory is accessed.&lt;/p&gt;
&lt;h2&gt;Production at hundreds-of-petabytes scale: architecture and optimizations&lt;/h2&gt;
&lt;p&gt;Our production clusters now manage hundreds of petabytes of data, deliver hundreds of GB/s of bandwidth, and provide petabyte-scale cache capacity. To improve data preparation and workload read performance, we optimized cache orchestration, model delivery, network transport, and data formats.&lt;/p&gt;
&lt;h3&gt;Cache orchestration: building caches as data arrives and proactively warming hot data&lt;/h3&gt;
&lt;p&gt;Based on statistics collected through our SDK, we found that roughly 80% of the data is accessed within eight days after it arrives. Therefore, we build distributed caches asynchronously as data is ingested and plan cache capacity and TTLs based on access patterns, so that workloads can read data from the cache. Cached data is reclaimed when it expires or when cache capacity becomes insufficient.&lt;/p&gt;&lt;/div&gt;
&lt;div class="w-block-ImageWithCaption block-ImageWithCaption"&gt;&lt;dl&gt;
    &lt;dt&gt;image&lt;/dt&gt;
    &lt;dd&gt;Cache lifecycle driven by hotspot windows and TTLs&lt;/dd&gt;
    &lt;dt&gt;caption&lt;/dt&gt;
    &lt;dd&gt;Cache lifecycle driven by hotspot windows and TTLs&lt;/dd&gt;
&lt;/dl&gt;&lt;/div&gt;
&lt;div class="w-block-markdown block-markdown"&gt;&lt;p&gt;For workloads that need explicit control over data preparation, we introduced &lt;a href="https://en.wikipedia.org/wiki/Fluid"&gt;Fluid&lt;/a&gt; for proactive orchestration. A Dataset describes the dataset and its source, while applications access the data through the corresponding Kubernetes PVC.&lt;/p&gt;
&lt;p&gt;As part of the workload workflow, DataLoad works with the JuiceFS Runtime to warm the data. The application starts consuming the data only after it’s ready. The Fluid Controller coordinates resources and state throughout the process, managing the lifecycle from cache creation and application consumption to cache reclamation. For workloads that are not integrated with Fluid, we also provide APIs that allow applications to control cache warming and eviction themselves.&lt;/p&gt;&lt;/div&gt;
&lt;div class="w-block-ImageWithCaption block-ImageWithCaption"&gt;&lt;dl&gt;
    &lt;dt&gt;image&lt;/dt&gt;
    &lt;dd&gt;Fluid-based cache warm-up and lifecycle orchestration&lt;/dd&gt;
    &lt;dt&gt;caption&lt;/dt&gt;
    &lt;dd&gt;Fluid-based cache warm-up and lifecycle orchestration&lt;/dd&gt;
&lt;/dl&gt;&lt;/div&gt;
&lt;div class="w-block-markdown block-markdown"&gt;&lt;h3&gt;Inference workloads: large-scale model delivery&lt;/h3&gt;
&lt;p&gt;For inference workloads, data preparation primarily means delivering models. An inference Pod cannot start serving requests until its model has been loaded. Previously, Pods loaded models directly from the model repository at startup. As the number of nodes increased, the repository had to handle a large number of repeated reads. Therefore, we placed a cache layer between the model repository and inference nodes.&lt;/p&gt;
&lt;p&gt;With this cache layer, models are first warmed up into the distributed cache and then distributed over the cache network to the local caches on inference nodes. Requests for the same data block are routed to the same cache node through consistent hashing, allowing the cache layer to aggregate I/O and reduce repeated reads from the source.&lt;/p&gt;
&lt;p&gt;When multiple inference Pods load the same model, the shared cache can aggregate their read requests and keep the amount of data fetched from the model repository close to the size of a single copy of the model. &lt;strong&gt;In our internal inference workloads, this approach improved deployment speed by more than 10× compared with the previous architecture.&lt;/strong&gt;&lt;/p&gt;&lt;/div&gt;
&lt;div class="w-block-ImageWithCaption block-ImageWithCaption"&gt;&lt;dl&gt;
    &lt;dt&gt;image&lt;/dt&gt;
    &lt;dd&gt;Inference model delivery through shared caching&lt;/dd&gt;
    &lt;dt&gt;caption&lt;/dt&gt;
    &lt;dd&gt;Inference model delivery through shared caching&lt;/dd&gt;
&lt;/dl&gt;&lt;/div&gt;
&lt;div class="w-block-markdown block-markdown"&gt;&lt;h3&gt;Training workloads: TCP zero-copy optimization&lt;/h3&gt;
&lt;p&gt;Once data is in the cache, workloads still need to continuously read it over the network. To reduce the overhead of this path, we optimized data transfer between clients and cache nodes, starting with TCP because it applies to a broad range of environments.&lt;/p&gt;
&lt;p&gt;In the conventional read path, &lt;code&gt;ReadAt&lt;/code&gt; copies data from kernel space into a user-space buffer, and then &lt;code&gt;conn.Write&lt;/code&gt; copies it back into the kernel for transmission. When the requested data is available in &lt;code&gt;cacheFile&lt;/code&gt; on the server and the requested range is valid, we can use &lt;code&gt;io.CopyN → sendfile(2)&lt;/code&gt; to send the file data directly to the TCP socket. This eliminates this user-space copy.&lt;/p&gt;&lt;/div&gt;
&lt;div class="w-block-ImageWithCaption block-ImageWithCaption"&gt;&lt;dl&gt;
    &lt;dt&gt;image&lt;/dt&gt;
    &lt;dd&gt;Zero-copy TCP send path for cache hits&lt;/dd&gt;
    &lt;dt&gt;caption&lt;/dt&gt;
    &lt;dd&gt;Zero-copy TCP send path for cache hits&lt;/dd&gt;
&lt;/dl&gt;&lt;/div&gt;
&lt;div class="w-block-markdown block-markdown"&gt;&lt;p&gt;To evaluate the performance of the optimized cache path, we ran a 1 MiB sequential-read benchmark. The combined bandwidth across multiple servers was 1,200 Gbit/s. As client load increased, measured throughput reached approximately 135–138 GiB/s. At around 135 GiB/s, P99 latency for 1 MiB requests was approximately 2 ms. When throughput increased further to around 138 GiB/s, P99 latency rose to approximately 20–30 ms. This shows that as throughput approaches the bandwidth ceiling, a trade-off remains between throughput and tail latency.&lt;/p&gt;&lt;/div&gt;
&lt;div class="w-block-ImageWithCaption block-ImageWithCaption"&gt;&lt;dl&gt;
    &lt;dt&gt;image&lt;/dt&gt;
    &lt;dd&gt;Sequential read benchmark&lt;/dd&gt;
    &lt;dt&gt;caption&lt;/dt&gt;
    &lt;dd&gt;Sequential read benchmark&lt;/dd&gt;
&lt;/dl&gt;&lt;/div&gt;
&lt;div class="w-block-markdown block-markdown"&gt;&lt;p&gt;For the throughput-oriented MLPerf Storage UNet3D workload, we first used a high-density single-client topology. We concentrated the concurrent read load from eight accelerator ranks on a single node with a single 200 Gbit/s data ingress, allowing us to measure the data delivery ceiling of a single client. The tests covered three accelerator configurations: H20, H100, and B200. The H100 and B200 tests reached the limits of the 200G network and the client read path, shifting the bottleneck from backend storage to the client data ingress. In the next phase, we’ll extend the UNet3D training workload to multiple clients and combine it with RDMA to further evaluate sustained data delivery and accelerator utilization for large-scale, multi-node, multi-accelerator training.&lt;/p&gt;&lt;/div&gt;
&lt;div class="w-block-ImageWithCaption block-ImageWithCaption"&gt;&lt;dl&gt;
    &lt;dt&gt;image&lt;/dt&gt;
    &lt;dd&gt;Theoretical bandwidth requirements and measured results for MLPerf UNet3D&lt;/dd&gt;
    &lt;dt&gt;caption&lt;/dt&gt;
    &lt;dd&gt;Theoretical bandwidth requirements and measured results for MLPerf UNet3D&lt;/dd&gt;
&lt;/dl&gt;&lt;/div&gt;
&lt;div class="w-block-markdown block-markdown"&gt;&lt;h3&gt;Lance columnar storage: reducing I/O at the data format layer&lt;/h3&gt;
&lt;p&gt;In addition to improving storage-path throughput, we also reduced the amount of data and number of I/O operations required by workloads by changing the data format.&lt;/p&gt;
&lt;p&gt;For example, consider labeling data. A single asset may correspond to multiple JSON files, which were previously packaged into tar archives. Downstream processing still had to parse the JSON frame by frame, resulting in repeated serialization and format conversion and generating a large number of small I/O operations.&lt;/p&gt;
&lt;p&gt;We switched the labeling data to Lance and flattened commonly used JSON fields into columns. Data is passed in memory through Arrow batches and written to Lance tables in batches. Downstream workloads select only the required columns and read them in batches, reducing unnecessary reads, per-frame JSON processing, and repeated serialization.&lt;/p&gt;&lt;/div&gt;
&lt;div class="w-block-ImageWithCaption block-ImageWithCaption"&gt;&lt;dl&gt;
    &lt;dt&gt;image&lt;/dt&gt;
    &lt;dd&gt;Per-frame JSON processing vs. batched data flow with Lance&lt;/dd&gt;
    &lt;dt&gt;caption&lt;/dt&gt;
    &lt;dd&gt;Per-frame JSON processing vs. batched data flow with Lance&lt;/dd&gt;
&lt;/dl&gt;&lt;/div&gt;
&lt;div class="w-block-markdown block-markdown"&gt;&lt;p&gt;The benefits vary across pipelines. &lt;strong&gt;I/O time decreased by approximately 20%–90%, IOPS requirements decreased by approximately 90%, and bandwidth consumption decreased by more than 60%.&lt;/strong&gt; These improvements significantly reduced the demand that application workloads placed on storage resources.&lt;/p&gt;
&lt;h3&gt;Combining Lance with JuiceFS for targeted data warm-up&lt;/h3&gt;
&lt;p&gt;Column-based reads also allow us to make data warm-up more targeted. We use layout metadata such as the Lance Manifest to locate the physical byte ranges of the selected columns. Then, we map those ranges to the corresponding JuiceFS data blocks and warm only the required blocks, reducing unnecessary reads.&lt;/p&gt;&lt;/div&gt;
&lt;div class="w-block-ImageWithCaption block-ImageWithCaption"&gt;&lt;dl&gt;
    &lt;dt&gt;image&lt;/dt&gt;
    &lt;dd&gt;JuiceFS data blocks for targeted warm-up&lt;/dd&gt;
    &lt;dt&gt;caption&lt;/dt&gt;
    &lt;dd&gt;Mapping Lance columns to JuiceFS data blocks for targeted warm-up&lt;/dd&gt;
&lt;/dl&gt;&lt;/div&gt;
&lt;div class="w-block-markdown block-markdown"&gt;&lt;p&gt;These capabilities have been merged into JuiceFS Community Edition: byte-range data warm-up (&lt;a href="https://github.com/juicedata/juicefs/pull/7398"&gt;PR #7398&lt;/a&gt;) and a tool for parsing Lance datasets (&lt;a href="https://github.com/juicedata/juicefs/pull/7399"&gt;PR #7399&lt;/a&gt;). Together, they can generate a list of files and byte ranges based on a specified dataset version and selected columns, which can then be used for targeted data warm-up.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Looking back at this evolution, we built a unified data platform on JuiceFS and gradually improved it along three paths:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;A stable access layer:&lt;/strong&gt; The unified access layer abstracts differences between underlying storage systems. This minimizes the impact of storage scaling and deployment changes on application integration.  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Shared hot data:&lt;/strong&gt; Distributed caching allows data to be reused across nodes. This reduces repeated reads from the source when workloads move between nodes, clusters scale out, or multiple copies of the same data are accessed.  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Proactive data preparation:&lt;/strong&gt; Fluid orchestration and APIs allow data to be prepared before workloads consume it. This connects workload execution to the state of data preparation.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Together, these three approaches support data delivery at the hundreds-of-petabytes scale and performance requirements of hundreds of GB/s and above, while reducing the operational overhead and coordination required between storage and application teams. We continue to optimize cache orchestration, network transport, and data formats to make data available faster and reduce compute wait time, providing a more reliable storage foundation for autonomous driving R&amp;amp;D.&lt;/p&gt;
&lt;p&gt;If you have any feedback on this article or ideas to share, we invite you to participate in the &lt;a href="https://github.com/juicedata/juicefs/discussions/"&gt;discussions on GitHub&lt;/a&gt; and join &lt;a href="http://go.juicefs.com/discord"&gt;our community on Discord&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;</description><pubDate>Thu, 29 Oct 2026 05:36:00 +0000</pubDate><guid>https://www.juicefs.com/en/blog/user-stories/build-petabyte-scale-data-platform-self-driving-with-juicefs</guid></item><item><title>Scaling Data Management for Agent Sandboxes with JuiceFS</title><link>https://www.juicefs.com/en/blog/solutions/scaling-agent-sandboxes-juicefs</link><description>&lt;div class="w-block-markdown block-markdown"&gt;&lt;p&gt;Recently, while working with cloud providers and agent teams to deploy sandboxes, we found that beyond getting data into the sandbox, we also need to consider how the data required by tasks and the data generated during execution can be continuously used across tasks and stages. Sandboxes can be quickly created and destroyed with tasks, but data often needs to be retained, shared, and transferred.  &lt;/p&gt;
&lt;p&gt;As sandbox concurrency scales further, the challenges go beyond data persistence and shared access. Operational issues such as client scale, cache reuse, small files, and fault isolation become more prominent. &lt;/p&gt;
&lt;p&gt;This article combines our practice in agentic &lt;a href="https://en.wikipedia.org/wiki/Reinforcement_learning"&gt;reinforcement learning&lt;/a&gt; (RL) scenarios and &lt;a href="https://juicefs.com/docs/community/introduction/"&gt;JuiceFS&lt;/a&gt; deployment experience in cloud provider sandboxes to introduce how sandbox data is organized, accessed across clouds, and mounted. We’ll also discuss the problems and optimization directions encountered under large-scale concurrency.&lt;/p&gt;
&lt;h2&gt;How to manage long-lived data in short-lived sandboxes&lt;/h2&gt;
&lt;p&gt;Take agentic RL as an example. A task typically goes through task distribution, sandbox execution, trajectory collection, reward evaluation, and training optimization. Data generated during task execution continues to be used by subsequent stages.  &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;First, the compute lifecycle and data lifecycle separate.&lt;/strong&gt; When an agent task starts, it needs to read datasets, code repositories, dependency environments, and model weights. During execution, it continuously produces trajectories, logs, intermediate files, and evaluation results. The sandbox can be destroyed after the task ends, but some of this data still needs to be retained for replay, analysis, evaluation, and subsequent training.  &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Second, data sharing and task isolation must coexist.&lt;/strong&gt; Each sandbox typically needs an independent working directory and access boundary, but different agents, evaluators, or training pipelines may access the same dataset, code repository, or reuse results from previous tasks.  &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Third, data needs to flow across different compute environments.&lt;/strong&gt; When tasks are distributed across self-built environments and sandboxes from different cloud providers, maintaining independent data copies in each environment not only increases synchronization and management costs but also limits the flexibility of task scheduling.&lt;/p&gt;
&lt;h2&gt;How JuiceFS manages and accesses sandbox data&lt;/h2&gt;
&lt;p&gt;To address these data management issues, we introduce how JuiceFS organizes and accesses data in actual sandbox environments.&lt;/p&gt;
&lt;h3&gt;Organizing shared data and task data with directories&lt;/h3&gt;
&lt;p&gt;Different customers adopt different data organization methods based on their application characteristics. Based on the usage patterns of existing customers, a typical approach is:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Datasets directory&lt;/strong&gt;: stores core data such as evaluation datasets, training datasets, and benchmark task inputs.  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Repo directory&lt;/strong&gt;: stores code repositories, toolkits, and snapshots of related dependency environments.  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Task directories&lt;/strong&gt;: based on different tasks, runtime IDs, and training versions, independent directories are created in the file system to store data generated during each task run.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In this way, public data such as datasets and repos can be shared and accessed by multiple tasks, while each task has its own independent data space. At the same time, enterprises can decide which data needs to be retained long-term and which can be cleaned up after task completion, enabling more flexible data lifecycle management.&lt;/p&gt;
&lt;h3&gt;How cross-cloud sandboxes access the same data&lt;/h3&gt;
&lt;p&gt;Some customers use sandbox services from different providers across multiple cloud platforms simultaneously for reasons such as security, load balancing, and resource scheduling.&lt;/p&gt;&lt;/div&gt;
&lt;div class="w-block-ImageWithCaption block-ImageWithCaption"&gt;&lt;dl&gt;
    &lt;dt&gt;image&lt;/dt&gt;
    &lt;dd&gt;Multi-cloud compute access&lt;/dd&gt;
    &lt;dt&gt;caption&lt;/dt&gt;
    &lt;dd&gt;Multi-cloud compute access&lt;/dd&gt;
&lt;/dl&gt;&lt;/div&gt;
&lt;div class="w-block-markdown block-markdown"&gt;&lt;p&gt;Our customers' core data (such as training sets and inference data) is usually stored in their own data platform or file system, while sandbox environments from different cloud providers run on their respective cloud infrastructures. The challenge is how sandboxes on different clouds can access the same data without maintaining separate data copies.&lt;/p&gt;
&lt;p&gt;In such scenarios, &lt;a href="https://juicefs.com/docs/cloud/"&gt;JuiceFS Enterprise Edition&lt;/a&gt;'s cross-cloud data access capability can be used to keep unified data on the customer's own platform while allowing sandboxes in different cloud environments to access it on demand. With fine-grained permission control, data isolation can be achieved between sandboxes, and resources such as datasets, code repositories, and evaluation data on different clouds can be managed within a unified namespace.&lt;/p&gt;
&lt;p&gt;For example, after data is written from cloud A, a sandbox in cloud B can quickly read it and continue the subsequent task flow. This improves the flexibility of task scheduling and reduces the complexity of data management in multi-cloud environments.&lt;/p&gt;
&lt;h3&gt;JuiceFS data mounting mode for strongly isolated sandboxes&lt;/h3&gt;
&lt;p&gt;To enable sandboxes to actually access this data, we also need to solve the problem of &lt;strong&gt;how to mount the file system into isolated environments&lt;/strong&gt;.  &lt;/p&gt;
&lt;p&gt;Currently, sandbox solutions provided by cloud providers are different somewhat from self-built sandboxes in enterprises. From the existing cloud sandbox architectures, most are based on lightweight virtualization technologies such as &lt;a href="https://firecracker-microvm.github.io/"&gt;Firecracker&lt;/a&gt;, with each cloud provider optimizing to different degrees.  &lt;/p&gt;
&lt;p&gt;The core characteristic of such sandboxes is that they create a strongly isolated environment inside a virtual machine. This keeps it isolated from the host and other sandbox instances. Therefore, under this strong isolation architecture, data access cannot simply rely on host shared directories. &lt;/p&gt;
&lt;p&gt;To address this, the current approach is to run an independent JuiceFS client alongside each sandbox. The client is launched with the sandbox through a sidecar-like mechanism provided by the cloud provider and exposes a local mount path to the application sandbox.&lt;br&gt;
In this mode, each sandbox connects to the backend JuiceFS service with an independent identity, accesses the metadata service deployed in the customer environment through the VPC network, reads data from the corresponding &lt;a href="https://en.wikipedia.org/wiki/Object_storage"&gt;object storage&lt;/a&gt;, and mounts shared or exclusive directories as needed by the task. For data that needs to be shared across multiple tasks and components, a shared directory enables unified access, while data unique to each task is isolated and protected through independent subdirectories, ensuring data security.&lt;/p&gt;
&lt;p&gt;For permission management, the token access control capability provided by JuiceFS Enterprise Edition can further enable fine-grained permission management, ensuring secure and controllable data access between different sandboxes.&lt;/p&gt;
&lt;h2&gt;JuiceFS in cloud provider sandboxes&lt;/h2&gt;
&lt;p&gt;We’ve implemented JuiceFS in sandbox environments on &lt;a href="https://en.wikipedia.org/wiki/Tencent_Cloud"&gt;Tencent Cloud&lt;/a&gt; and &lt;a href="https://en.wikipedia.org/wiki/Alibaba_Cloud"&gt;Alibaba Cloud&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Tencent Cloud: data mounting methods in agent runtime&lt;/h3&gt;
&lt;p&gt;Tencent Cloud uses the agent runtime mechanism, with three levels of isolation: file system level, instance level, and storage level.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;The first level is mounting block storage inside the sandbox.&lt;/strong&gt; The block storage is exclusively used by a single sandbox, and the sandbox creates an independent file system on it. In this case, other environments cannot access this file system, achieving strong data isolation.  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The second level is mounting storage services provided by Tencent Cloud itself.&lt;/strong&gt; Through mount, the corresponding storage can be mounted into a specific sandbox environment, which is essentially mounting inside the sandbox.  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The third level is the JuiceFS file system or subdirectory-level isolation.&lt;/strong&gt; JuiceFS can mount the entire file system to a sandbox or only a specified subdirectory (subpath). Multiple sandboxes can share the same JuiceFS file system while dividing their data access scopes through different subdirectories, striking a balance between data sharing and task isolation.&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;
&lt;div class="w-block-ImageWithCaption block-ImageWithCaption"&gt;&lt;dl&gt;
    &lt;dt&gt;image&lt;/dt&gt;
    &lt;dd&gt;Tencent Cloud agent sandbox file isolation solution&lt;/dd&gt;
    &lt;dt&gt;caption&lt;/dt&gt;
    &lt;dd&gt;Tencent Cloud agent sandbox file isolation solution&lt;/dd&gt;
&lt;/dl&gt;&lt;/div&gt;
&lt;div class="w-block-markdown block-markdown"&gt;&lt;h3&gt;Alibaba Cloud: FC and ACS&lt;/h3&gt;
&lt;p&gt;Alibaba Cloud has two product lines:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The Function Compute (FC) Sandbox: Its implementation is similar to Tencent Cloud, also using a sidecar-like process mode to start a client in each sandbox to complete JuiceFS mounting.  &lt;/li&gt;
&lt;li&gt;The Container Compute Service (ACS): It also provides sandbox services but with a different implementation. ACS integrates JuiceFS mounting capability into its driver component. In actual use, customers decide whether and how to use this capability. The related code is also planned to be open-sourced in its components.&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;
&lt;div class="w-block-ImageWithCaption block-ImageWithCaption"&gt;&lt;dl&gt;
    &lt;dt&gt;image&lt;/dt&gt;
    &lt;dd&gt;Alibaba Cloud FC agent sandbox&lt;/dd&gt;
    &lt;dt&gt;caption&lt;/dt&gt;
    &lt;dd&gt;Alibaba Cloud FC agent sandbox&lt;/dd&gt;
&lt;/dl&gt;&lt;/div&gt;
&lt;div class="w-block-markdown block-markdown"&gt;&lt;p&gt;Currently, whether on Tencent Cloud or Alibaba Cloud, JuiceFS mounting capability supports both Community Edition and Enterprise Edition.&lt;/p&gt;
&lt;h3&gt;Sandbox lifecycle management and mount control&lt;/h3&gt;
&lt;p&gt;In the current sidecar-like client mode, JuiceFS mounting is completed during sandbox startup, and the entire mount lifecycle is managed by the sandbox platform. For example, in Alibaba Cloud, the FC management platform is responsible; in Tencent Cloud, the agent runtime platform takes on this role.  &lt;/p&gt;
&lt;p&gt;Each sandbox corresponds to an independent JuiceFS client, which is created with the sandbox and completes directory mounting. The token, mount parameters, cache directory, and other configurations required during mounting are uniformly injected and managed by the runtime platform.  &lt;/p&gt;
&lt;p&gt;Under this mechanism, there are some differences between the Enterprise Edition and the Community Edition. JuiceFS Enterprise Edition provides more comprehensive management through the console and token capabilities, and cloud provider platforms have largely integrated these capabilities into their own mount management processes.  &lt;/p&gt;
&lt;p&gt;For the application side, the sandbox only needs to see the mounted data directory and does not need to directly manage the JuiceFS client. The creation, configuration, mounting, and exit of the client are all handled by the sandbox platform.&lt;/p&gt;
&lt;h2&gt;Challenges and optimization in large-scale agent sandbox scenarios&lt;/h2&gt;
&lt;h3&gt;Client scaling bottleneck&lt;/h3&gt;
&lt;p&gt;Currently, one sandbox corresponds to one independent JuiceFS client, and each client is considered an independent client instance in the Enterprise Edition. As the number of sandboxes grows, the number of clients and the corresponding processes, connections, and metadata requests also increase.  &lt;/p&gt;
&lt;p&gt;However, most cloud provider sandbox implementations are based on Firecracker virtualization, and native Firecracker does not support passthrough mounting like VirtIO-FS. The number of clients a single file system can support is around 100,000. We’ve already received requests from some customers for millions or even more sandboxes. This makes client architecture optimization an important direction for future evolution.&lt;/p&gt;
&lt;p&gt;One direction being explored is introducing a Mount Pod-like mode, where a JuiceFS client runs on the host or a designated node, and multiple sandboxes share the mounting capability. This can reduce the number of client instances and resource consumption, and further increase the supported sandbox scale.&lt;/p&gt;
&lt;h3&gt;Cache reuse and data loading efficiency&lt;/h3&gt;
&lt;p&gt;Currently, one sandbox corresponds to one independent JuiceFS client, and sandboxes may be distributed across different nodes. This makes it difficult to fully reuse client cache across tasks. Without a shared cache layer, a large amount of repeated data reads and loading pressure is directly transmitted to object storage; for cross-cloud sandbox scenarios, it may further increase bandwidth pressure on cross-cloud links.  &lt;/p&gt;
&lt;p&gt;To address this, we plan to combine task scheduling, host disk resources, and &lt;a href="https://juicefs.com/docs/community/guide/cache/"&gt;JuiceFS caching&lt;/a&gt; capabilities to improve cache reuse efficiency for hot data. For example, schedule related tasks to nearby nodes as much as possible, and use host disks to build a distributed cache, bringing frequently accessed data such as model datasets as close to compute as possible and reducing repeated loading from object storage.  &lt;/p&gt;
&lt;p&gt;When using cloud provider sandboxes, it’s necessary to combine the cache resources the cloud provider can offer; for self-built sandboxes, planning can be based on the customer's own infrastructure to balance performance, cache capacity, and resource cost.&lt;/p&gt;
&lt;h3&gt;Small files and metadata performance&lt;/h3&gt;
&lt;p&gt;During agent execution, data such as logs and trajectories often manifests as continuous small I/O writes, large numbers of small files, and frequent flushes. This places higher demands on JuiceFS metadata and write performance.  &lt;/p&gt;
&lt;p&gt;For such scenarios, we’ll work with application teams to explore optimization strategies, such as evaluating whether large numbers of small I/Os can be merged into larger-grained write requests, or using batch writes to reduce frequent small file operations. Adjusting the data write pattern on the application side can also help reduce pressure on the underlying metadata service.&lt;/p&gt;
&lt;h3&gt;Fault isolation and platform governance&lt;/h3&gt;
&lt;p&gt;In large-scale concurrency scenarios, it’s necessary to prevent a single abnormal task from affecting shared caches, metadata services, or object storage. For example, when abnormal access generates a large number of requests, its impact scope must be controlled as much as possible to avoid affecting other tasks.  &lt;/p&gt;
&lt;p&gt;If shared caches, shared clients, or client pools are further introduced, the original isolation boundaries will also change. After multiple sandboxes share underlying resources, fault isolation, resource limits, access permissions, and lifecycle management of shared clients need to be reconsidered.  &lt;/p&gt;
&lt;p&gt;On the other hand, as more platforms treat sandboxes as a public service for different teams or customers, data management will further extend to &lt;a href="https://en.wikipedia.org/wiki/Multitenancy"&gt;multi-tenant&lt;/a&gt; scenarios. Clear data and permission boundaries must be maintained between tenants, and different types of data require corresponding lifecycle policies.  &lt;/p&gt;
&lt;p&gt;Observability also needs to be improved accordingly, not only to observe client and cache status but also to understand overall storage usage, the running status of shared resources, and the scope of abnormal impact. This will provide a basis for subsequent resource governance.  &lt;/p&gt;
&lt;p&gt;From current practice, sandboxes are not difficult to create and destroy quickly; the real challenge is that the data behind them cannot disappear with them. Trajectories, logs, evaluation results, and training samples still need to be used by subsequent tasks, which makes storage gradually evolve from "providing a directory for the sandbox" to participating in the entire agent data pipeline over the long term.  &lt;/p&gt;
&lt;p&gt;As the scale grows from hundreds of thousands to millions, designs that were once simple and straightforward, such as sandbox clients and independent caches, also need to be reconsidered. We are still validating different approaches for client reuse, caching, and isolation, and we welcome exchanges with teams working on agent sandboxes, agentic RL, or related infrastructure about the problems they encounter. &lt;/p&gt;
&lt;p&gt;If you have any feedback on this article or ideas to share, we invite you to participate in the &lt;a href="https://github.com/juicedata/juicefs/discussions/"&gt;discussions on GitHub&lt;/a&gt; and join &lt;a href="http://go.juicefs.com/discord"&gt;our community on Discord&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;</description><pubDate>Thu, 22 Oct 2026 05:57:00 +0000</pubDate><guid>https://www.juicefs.com/en/blog/solutions/scaling-agent-sandboxes-juicefs</guid></item><item><title>How to Access JuiceFS via S3 and WebDAV Protocols</title><link>https://www.juicefs.com/en/blog/engineering/access-juicefs-via-s3-webdav-protocols</link><description>&lt;div class="w-block-markdown block-markdown"&gt;&lt;p&gt;Different applications access data in different ways: some rely on &lt;a href="https://en.wikipedia.org/wiki/POSIX"&gt;POSIX&lt;/a&gt; file interfaces, some are built on the S3 API, and some users want to browse and edit remote files through a file manager. &lt;a href="https://juicefs.com/docs/community/introduction/"&gt;JuiceFS&lt;/a&gt;' multi-protocol access capability is designed precisely to let these tools access the same file system.  &lt;/p&gt;
&lt;p&gt;In this article, we'll explain the shared initialization path of S3 Gateway and WebDAV, describe their applicable scenarios and common mappings, and dive into their implementation principles and boundaries.&lt;/p&gt;
&lt;h2&gt;A shared initialization path&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://juicefs.com/docs/community/architecture"&gt;JuiceFS consists of a metadata engine and object storage&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The metadata engine manages directories, attributes, locks, and sessions.  &lt;/li&gt;
&lt;li&gt;Object storage stores the actual file data blocks.&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;
&lt;div class="w-block-ImageWithCaption block-ImageWithCaption"&gt;&lt;dl&gt;
    &lt;dt&gt;image&lt;/dt&gt;
    &lt;dd&gt;1JuiceFS 架构图.drawio&lt;/dd&gt;
    &lt;dt&gt;caption&lt;/dt&gt;
    &lt;dd&gt;JuiceFS Community Edition architecture&lt;/dd&gt;
&lt;/dl&gt;&lt;/div&gt;
&lt;div class="w-block-markdown block-markdown"&gt;&lt;p&gt;From an implementation perspective, S3 Gateway and WebDAV first go through the same service initialization path. The service process creates a JuiceFS client based on the metadata address, listen address, and common parameters such as subdir, read-only, cache, limits, access-log, and metrics. Then, it initializes the metadata client, object storage, data block cache, and VFS configuration in sequence, ultimately obtaining an &lt;code&gt;fs.FileSystem&lt;/code&gt;.&lt;/p&gt;&lt;/div&gt;
&lt;div class="w-block-ImageWithCaption block-ImageWithCaption"&gt;&lt;dl&gt;
    &lt;dt&gt;image&lt;/dt&gt;
    &lt;dd&gt;Shared service initialization path of S3 Gateway and WebDAV&lt;/dd&gt;
    &lt;dt&gt;caption&lt;/dt&gt;
    &lt;dd&gt;Shared service initialization path of S3 Gateway and WebDAV&lt;/dd&gt;
&lt;/dl&gt;&lt;/div&gt;
&lt;div class="w-block-markdown block-markdown"&gt;&lt;p&gt;In other words, the common foundation of the two is not a FUSE mount point, but a native JuiceFS client with sessions, caching, metrics, and background tasks. Before S3 requests and WebDAV requests enter their respective protocol adaptation layers, they already share the same JuiceFS file system and the same file system namespace.&lt;/p&gt;
&lt;h2&gt;Applicable scenarios and common mappings&lt;/h2&gt;
&lt;p&gt;The shared initialization path explains how the two connect to the same file system. In actual use, what matters more is choosing the access method: which scenarios are suitable for S3 Gateway, which are suitable for WebDAV, and how common requests map to JuiceFS operations.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Linux applications, training jobs, or workloads requiring full file system semantics should prefer FUSE/CSI.  &lt;/li&gt;
&lt;li&gt;Applications already built on the S3 SDK, AWS CLI, MinIO Client, or object storage toolchains should prefer S3 Gateway.  &lt;/li&gt;
&lt;li&gt;Desktop file manager access, DAV/rclone synchronization, Office/apps collaboration, and simple sharing should prefer WebDAV.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Mapping of common S3 Gateway APIs to JuiceFS file system operations:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style="text-align: left;"&gt;S3 API&lt;/th&gt;
&lt;th style="text-align: left;"&gt;Purpose&lt;/th&gt;
&lt;th style="text-align: left;"&gt;Equivalent file system operation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;GetObject&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Download an object&lt;/td&gt;
&lt;td style="text-align: left;"&gt;open/read&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;PutObject&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Upload or overwrite an object&lt;/td&gt;
&lt;td style="text-align: left;"&gt;create/write/rename&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;HeadObject&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Query object metadata&lt;/td&gt;
&lt;td style="text-align: left;"&gt;stat/getxattr&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;DeleteObject(s)&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Delete one or more objects&lt;/td&gt;
&lt;td style="text-align: left;"&gt;unlink/remove&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;ListObjects V1/V2&lt;/td&gt;
&lt;td style="text-align: left;"&gt;List objects by prefix&lt;/td&gt;
&lt;td style="text-align: left;"&gt;readdir+filter&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;CopyObject&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Copy an object server-side&lt;/td&gt;
&lt;td style="text-align: left;"&gt;copy/read+write&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;MakeBucket&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Create a bucket&lt;/td&gt;
&lt;td style="text-align: left;"&gt;mkdir&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;DeleteBucket&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Delete an empty bucket&lt;/td&gt;
&lt;td style="text-align: left;"&gt;rmdir&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;NewMultipartUpload&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Create a multipart upload session&lt;/td&gt;
&lt;td style="text-align: left;"&gt;create&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;PutObjectPart&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Write a part&lt;/td&gt;
&lt;td style="text-align: left;"&gt;write&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;CompleteMultipart&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Merge and commit the object&lt;/td&gt;
&lt;td style="text-align: left;"&gt;copy + atomic rename&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;Tags/Metadata&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Read/write tags and metadata&lt;/td&gt;
&lt;td style="text-align: left;"&gt;get/setxattr&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Mapping of common WebDAV methods to JuiceFS file system operations:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style="text-align: left;"&gt;HTTP method&lt;/th&gt;
&lt;th style="text-align: left;"&gt;Purpose&lt;/th&gt;
&lt;th style="text-align: left;"&gt;Equivalent file system operation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;GET&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Download a file&lt;/td&gt;
&lt;td style="text-align: left;"&gt;read&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;PUT&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Upload or overwrite a file&lt;/td&gt;
&lt;td style="text-align: left;"&gt;write/create&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;DELETE&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Delete a file or directory&lt;/td&gt;
&lt;td style="text-align: left;"&gt;remove&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;MKCOL&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Create a directory&lt;/td&gt;
&lt;td style="text-align: left;"&gt;mkdir&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;PROPFIND&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Query properties or list a directory&lt;/td&gt;
&lt;td style="text-align: left;"&gt;stat/readdir&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;PROPPATCH&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Modify custom properties&lt;/td&gt;
&lt;td style="text-align: left;"&gt;setxattr&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;COPY&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Copy a file or directory&lt;/td&gt;
&lt;td style="text-align: left;"&gt;cp&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;MOVE&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Move or rename&lt;/td&gt;
&lt;td style="text-align: left;"&gt;mv/rename&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;LOCK&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Lock resources&lt;/td&gt;
&lt;td style="text-align: left;"&gt;File lock&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;UNLOCK&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Unlock resources&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Release a file lock&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;OPTIONS&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Query server capabilities&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Capability negotiation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;HEAD&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Query HTTP metadata only&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Lightweight stat&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2&gt;S3 Gateway principles: from object semantics to file system operations&lt;/h2&gt;
&lt;p&gt;S3 Gateway converts S3 protocol requests into JuiceFS file system operations. This section covers four aspects:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The request path  &lt;/li&gt;
&lt;li&gt;Internal state  &lt;/li&gt;
&lt;li&gt;Key semantic conversions  &lt;/li&gt;
&lt;li&gt;Permission coordination&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Request path: from the MinIO S3 server to &lt;code&gt;jfsObjects&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;The MinIO S3 server handles the S3 protocol layer, including request routing, signature verification, authentication and authorization, and multipart upload orchestration. After requests pass through the protocol layer, they enter the &lt;code&gt;ObjectLayer&lt;/code&gt; implemented by JuiceFS, namely &lt;code&gt;jfsObjects&lt;/code&gt;. &lt;code&gt;jfsObjects&lt;/code&gt; converts object-level reads, writes, listings, deletions, and attribute access into JuiceFS file system calls.&lt;/p&gt;&lt;/div&gt;
&lt;div class="w-block-ImageWithCaption block-ImageWithCaption"&gt;&lt;dl&gt;
    &lt;dt&gt;image&lt;/dt&gt;
    &lt;dd&gt;Call relationship among&lt;/dd&gt;
    &lt;dt&gt;caption&lt;/dt&gt;
    &lt;dd&gt;Call relationship among MinIO S3 server, jfsObjects, and JuiceFS file system&lt;/dd&gt;
&lt;/dl&gt;&lt;/div&gt;
&lt;div class="w-block-markdown block-markdown"&gt;&lt;h3&gt;State storage: how the internal namespace carries the Gateway state&lt;/h3&gt;
&lt;p&gt;During request conversion, the Gateway does not only access user-visible object paths; it also uses an internal namespace to store state needed by the service itself. For example, &lt;code&gt;.sys/tmp&lt;/code&gt; is used for temporary writes, &lt;code&gt;.sys/uploads&lt;/code&gt; is used for multipart upload state, and &lt;code&gt;.minio.sys&lt;/code&gt; is used to store MinIO/IAM-related metadata.  &lt;/p&gt;
&lt;p&gt;These internal paths are not application data in the ordinary user's understanding, but they are the foundation the Gateway needs to maintain upload processes, part states, and permission configurations.&lt;/p&gt;
&lt;h3&gt;Semantic conversion: &lt;code&gt;PutObject&lt;/code&gt;, &lt;code&gt;Multipart&lt;/code&gt;, &lt;code&gt;Bucket&lt;/code&gt;, and &lt;code&gt;Metadata&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;The S3 object model and the file system model are not completely the same, so the Gateway needs to perform semantic conversions at several key points.  &lt;/p&gt;
&lt;p&gt;&lt;code&gt;PutObject&lt;/code&gt; must ensure that an object is visible only after the upload is complete. To prevent clients from reading incomplete objects, &lt;a href="https://juicefs.com/docs/community/guide/gateway/"&gt;JuiceFS S3 Gateway&lt;/a&gt; writes to a temporary file and saves object attributes such as metadata and tag, commits to the target path via rename after completion. Leveraging the atomicity of file system rename, the Gateway can switch an object write from “uncommitted” to “committed.”&lt;/p&gt;&lt;/div&gt;
&lt;div class="w-block-ImageWithCaption block-ImageWithCaption"&gt;&lt;dl&gt;
    &lt;dt&gt;image&lt;/dt&gt;
    &lt;dd&gt;PutObject write flow&lt;/dd&gt;
    &lt;dt&gt;caption&lt;/dt&gt;
    &lt;dd&gt;PutObject write flow: from temporary files to atomic rename commit&lt;/dd&gt;
&lt;/dl&gt;&lt;/div&gt;
&lt;div class="w-block-markdown block-markdown"&gt;&lt;p&gt;Multipart upload needs to merge multiple parts into the final object. JuiceFS S3 Gateway can use file system capabilities such as &lt;code&gt;CopyFileRange&lt;/code&gt; to combine already written parts and commit the final file via rename. This mainly adjusts file system metadata relationships rather than moving all data again.&lt;/p&gt;&lt;/div&gt;
&lt;div class="w-block-ImageWithCaption block-ImageWithCaption"&gt;&lt;dl&gt;
    &lt;dt&gt;image&lt;/dt&gt;
    &lt;dd&gt;Part merging and final commit flow&lt;/dd&gt;
    &lt;dt&gt;caption&lt;/dt&gt;
    &lt;dd&gt;Part merging and final commit flow of multipart upload&lt;/dd&gt;
&lt;/dl&gt;&lt;/div&gt;
&lt;div class="w-block-markdown block-markdown"&gt;&lt;p&gt;Bucket mapping handles the relationship between the object namespace and file paths. In single-bucket mode, the file system name corresponds to the bucket; in multi-bucket mode, top-level directories map to buckets. Object attributes such as metadata, tag, and ETag are stored through file extended attributes (xattr).&lt;/p&gt;
&lt;h3&gt;Permission coordination: IAM and multiple instances&lt;/h3&gt;
&lt;p&gt;S3 Gateway also needs to handle identity and permission information, including root users, regular users, policies, service accounts, and more. These configurations are stored in the JuiceFS file system through internal paths, allowing them to be reused across multiple Gateway instances.  &lt;/p&gt;
&lt;p&gt;Therefore, multiple Gateway instances can share the same set of IAM configurations; however, each instance caches IAM information, so permission changes are not synchronized instantaneously. In actual deployments, we need to consider the refresh cycle.&lt;/p&gt;
&lt;h2&gt;WebDAV principles: from file protocol to JuiceFS operations&lt;/h2&gt;
&lt;p&gt;WebDAV starts from a different point than S3 Gateway. It targets file access scenarios, with common clients including macOS Finder, DAV/rclone, and some Office/apps clients. Since the WebDAV protocol includes concepts such as files, directories, and attributes, it does not need to first handle the model conversion between buckets, objects, and keys on the one hand and paths and files on the other, unlike S3 Gateway.&lt;/p&gt;
&lt;h3&gt;Request path: from HTTP entry to &lt;code&gt;webdavFS&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;After a WebDAV request enters JuiceFS:  &lt;/p&gt;
&lt;p&gt;1.It passes through net/http and &lt;code&gt;indexHandler&lt;/code&gt;. This layer mainly handles HTTP entry-related capabilities, such as authentication, transport, and conversion of directory access requests.  &lt;/p&gt;
&lt;p&gt;2.The request enters &lt;code&gt;x/net/webdav.Handler&lt;/code&gt;, which handles the WebDAV protocol layer and converts protocol methods into file access requests that webdavFS can process.&lt;/p&gt;&lt;/div&gt;
&lt;div class="w-block-ImageWithCaption block-ImageWithCaption"&gt;&lt;dl&gt;
    &lt;dt&gt;image&lt;/dt&gt;
    &lt;dd&gt;WebDAV request path&lt;/dd&gt;
    &lt;dt&gt;caption&lt;/dt&gt;
    &lt;dd&gt;WebDAV request path: from HTTP entry to JuiceFS file system operations&lt;/dd&gt;
&lt;/dl&gt;&lt;/div&gt;
&lt;div class="w-block-markdown block-markdown"&gt;&lt;p&gt;3.After entering webdavFS, the file access requests passed in by the Handler are converted into JuiceFS file system calls such as open, create, read/write, rename, delete, and attribute setting. Since the WebDAV protocol is close to file system semantics, the focus here is not to rebuild an object model, but to handle how request methods, file open flags, and attribute states map onto JuiceFS operations.&lt;/p&gt;
&lt;h3&gt;State boundaries: dead properties and LOCK&lt;/h3&gt;
&lt;p&gt;WebDAV adaptation involves not only data reads and writes but also the protocol's own state. Dead properties can be saved as JSON in xattr, thus landing in JuiceFS' file attribute system; however, LOCK state is different—it's currently kept in the service process memory. Single-instance deployments usually have no problem; in multi-instance deployments, different instances cannot automatically synchronize lock state.  &lt;/p&gt;
&lt;p&gt;These limitations usually do not affect Finder browsing, simple sharing, or DAV/rclone synchronization. However, if an application strongly relies on WebDAV file lock semantics, deployment mode and client behavior need to be verified separately.  &lt;/p&gt;
&lt;p&gt;S3 Gateway and WebDAV share the same JuiceFS client initialization path and access the same file system namespace. The difference is that S3 Gateway needs to convert object semantics into file system operations, while WebDAV is closer to file access semantics.  &lt;/p&gt;
&lt;p&gt;Therefore, the choice of access method should ultimately depend on the application itself: whether it organizes data as objects or operates on data as files and directories.  &lt;/p&gt;
&lt;p&gt;If you have any feedback on this article or ideas to share, we invite you to participate in the &lt;a href="https://github.com/juicedata/juicefs/discussions/"&gt;discussions on GitHub&lt;/a&gt; and join &lt;a href="http://go.juicefs.com/discord"&gt;our community on Discord&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;</description><pubDate>Thu, 15 Oct 2026 01:11:00 +0000</pubDate><guid>https://www.juicefs.com/en/blog/engineering/access-juicefs-via-s3-webdav-protocols</guid></item><item><title>Nydus + JuiceFS: Reducing Container Startup Time for AI Inference from 116s to 1.4s</title><link>https://www.juicefs.com/en/blog/solutions/nydus-juicefs-ai-inference-container-image-acceleration</link><description>&lt;div class="w-block-markdown block-markdown"&gt;&lt;p&gt;In large-scale &lt;a href="https://www.ibm.com/think/topics/ai-inference"&gt;AI inference&lt;/a&gt; services, when a cluster scales out, newly added inference instances must go through a series of cold-start steps before they can serve requests: container image preparation, file system mounting, runtime and inference framework initialization, and model weight loading. As image sizes and model weights continue to grow, the time spent on data preparation becomes increasingly prominent. During large-scale scaling events, many instances start simultaneously, further increasing the concurrent pressure on the registry, network, and backend storage.  &lt;/p&gt;
&lt;p&gt;To address these issues, the industry has developed several optimization strategies, including reducing image size, using P2P distribution to alleviate concurrent pull pressure, and employing on-demand loading to reduce data transfer on the critical startup path.&lt;br&gt;
In this article, we’ll explore a shared‑storage‑based approach: combining &lt;a href="https://nydus.dev/"&gt;Nydus&lt;/a&gt;’ on‑demand image loading &lt;strong&gt;capabilities&lt;/strong&gt; with JuiceFS’ distributed storage and caching mechanisms. &lt;strong&gt;By sharing storage and reusing cached data, this approach reduces redundant data reads during large-scale scale-outs and shortens container startup time.&lt;/strong&gt; For AI inference scenarios, container images and model weights can be managed together under a unified storage, caching, and prefetching system, accelerating both types of data while reducing the complexity of building and maintaining two separate data pipelines.&lt;/p&gt;
&lt;h3&gt;Why OCI image distribution is slow&lt;/h3&gt;
&lt;p&gt;Traditional &lt;a href="https://en.wikipedia.org/wiki/Open_Container_Initiative"&gt;Open Container Initiative&lt;/a&gt; (OCI) images are typically organized as compressed tar layers. In the image‑pull mode, a node must fully download and extract the required layers before the container can start. In practice, &lt;strong&gt;however, only about 6%–20% of files in an image are actually accessed during container startup; the rest of the download and extraction overhead is wasted on non‑critical‑path data&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;In large clusters, this “prepare everything first, then start” approach causes three problems:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Long cold‑start times:&lt;/strong&gt; For GB‑sized images (like AI inference images), full download and extraction significantly delay new instance startup, often taking minutes.  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Registry bottleneck:&lt;/strong&gt; During HPA‑triggered bursts or large‑scale rollouts, hundreds of nodes simultaneously request GB‑sized layers from the registry, easily overwhelming the registry and congesting the network.  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Redundant network and storage usage:&lt;/strong&gt; Without an efficient P2P or distributed sharing mechanism between nodes, the same layers are repeatedly transferred across the cluster, resulting in significant bandwidth consumption and duplicated storage.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Dragonfly+Nydus: what it solves and what it leaves behind&lt;/h2&gt;
&lt;p&gt;To mitigate registry bandwidth pressure during concurrent image pulls in large clusters, a common solution is to introduce P2P distribution systems like Dragonfly. The core idea is to build a P2P distribution network via a scheduler and node‑side agents, allowing nodes to share image data and reduce egress traffic from the registry.  &lt;/p&gt;
&lt;p&gt;However, P2P distribution primarily optimizes the data transfer path; it does not change the fundamental OCI mechanism of downloading and extracting layers before starting the container. Nydus, on the other hand, changes the loading approach: it transforms “prepare everything then start” into “fetch lightweight metadata first, and then read actual data on demand,” reducing data transfer on the critical startup path.  &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Combined, Nydus handles on‑demand loading, while Dragonfly distributes the on‑demand data, reducing both the actual image read volume and the concurrent access pressure on the registry.&lt;/strong&gt;  &lt;/p&gt;
&lt;p&gt;However, this combination introduces additional infrastructure and operational complexity. Besides Nydus snapshotter, one must deploy and maintain Dragonfly’s scheduler, distributor, and node‑side components, and handle P2P network connectivity, cache space management, node anomalies, and cache eviction. In large‑scale GPU inference clusters, this means maintaining a separate data distribution and caching system independent of the storage layer.  &lt;/p&gt;
&lt;p&gt;This leads to an alternative thought: &lt;strong&gt;if the cluster already has a mature distributed file system like JuiceFS, could image data distribution and caching be offloaded to the shared storage system, reusing existing storage infrastructure while reducing the cost of building and maintaining extra P2P components&lt;/strong&gt;?&lt;/p&gt;
&lt;h2&gt;Architecture redesign: Nydus blobs hosted by JuiceFS&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;The core idea of the Nydus+JuiceFS solution is to transform image data distribution—originally relying on P2P network scheduling—into shared storage and cache reuse based on a distributed file system.&lt;/strong&gt; In this architecture, JuiceFS serves as the underlying unified data engine hosting Nydus image blob data, and worker nodes read data through the standard POSIX interface.&lt;/p&gt;&lt;/div&gt;
&lt;div class="w-block-ImageWithCaption block-ImageWithCaption"&gt;&lt;dl&gt;
    &lt;dt&gt;image&lt;/dt&gt;
    &lt;dd&gt;Nydus +JuiceFS&lt;/dd&gt;
    &lt;dt&gt;caption&lt;/dt&gt;
    &lt;dd&gt;Nydus +JuiceFS architecture and data flow&lt;/dd&gt;
&lt;/dl&gt;&lt;/div&gt;
&lt;div class="w-block-markdown block-markdown"&gt;&lt;p&gt;After an image is built and converted to Nydus format during the CI/CD phase, it’s split into two parts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Bootstrap (metadata): Very small (typically a few hundred KB, for example, ~450KB), stored in the Image Registry, used for fast indexing.  &lt;/li&gt;
&lt;li&gt;Blobs (actual data blocks): Contains all file content (typically several GB, for example, ~1GB), persisted directly to the JuiceFS shared file system after conversion (for example, &lt;code&gt;/var/lib/nydus/blobs&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When a worker node starts a container, containerd triggers nydus-snapshotter, and nydusd mounts the container’s read‑only layer via FUSE. Then, when the application issues actual read requests, nydusd looks up the index in the Bootstrap and reads the corresponding blob data on‑demand through the JuiceFS mount point.  &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The key change in this path is: the registry only distributes the manifest and the extremely lightweight bootstrap; the massive blob data transfer is entirely handled by JuiceFS’ distributed caching system. This fundamentally eliminates the registry network bottleneck during high‑concurrency pulls.&lt;/strong&gt;  &lt;/p&gt;
&lt;p&gt;For AI inference scenarios, this architecture can further unify the storage paths for images and model weights. In addition to Nydus image blobs, &lt;strong&gt;model weights can also be stored in JuiceFS&lt;/strong&gt;, allowing both types of data to reuse the same storage, caching, and prefetching mechanisms. This accelerates data loading while reducing the complexity of building and maintaining two data pipelines.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style="text-align: left;"&gt;Comparison basis&lt;/th&gt;
&lt;th style="text-align: left;"&gt;OCI full image pull&lt;/th&gt;
&lt;th style="text-align: left;"&gt;Dragonfly+Nydus&lt;/th&gt;
&lt;th style="text-align: left;"&gt;JuiceFS+Nydus&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;Core concept&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Full layer pull + layer extraction&lt;/td&gt;
&lt;td style="text-align: left;"&gt;P2P network offloading + on‑demand image loading&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Storage‑layer decoupling + distributed caching + on‑demand loading&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;Cold start method &amp;amp; time&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Full download and extraction required; typically 30s to 10min+&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Only download hundreds of kilobytes of bootstrap metadata and blobs needed for startup; usually seconds&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Only download hundreds of kilobytes of bootstrap metadata and blobs needed for startup; usually seconds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;Image data transfer path&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Registry → worker (full local download &amp;amp; extraction)&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Registry / source → Dragonfly P2P network → worker on‑demand read&lt;/td&gt;
&lt;td style="text-align: left;"&gt;JuiceFS → worker on‑demand read via POSIX, accelerated by local &amp;amp; distributed caches&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;Core components&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Registry + containerd&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Nydus, Manager, Scheduler, Seed Peer, and dfdaemon&lt;/td&gt;
&lt;td style="text-align: left;"&gt;JuiceFS + nydus‑snapshotter&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;Image &amp;amp; model weight synergy&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Image pulled from the registry to local node; model weights loaded via a separate path (NAS or object storage); two systems managed independently&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Images loaded on‑demand via Nydus, distributed by Dragonfly; model weights still rely on independent external storage&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Image blobs and model weights stored together in JuiceFS, sharing the same cache and warm-up mechanisms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;Operational complexity&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Easy to overwhelm registry bandwidth under high concurrency&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Requires extra maintenance of P2P scheduler, node network, and caching system&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Can reuse existing JuiceFS storage &amp;amp; cache infrastructure, reducing independent image distribution components&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;Local disk pressure&lt;/td&gt;
&lt;td style="text-align: left;"&gt;High: Stores full image and extracted data&lt;/td&gt;
&lt;td style="text-align: left;"&gt;High and unpredictable: Requires cache space for P2P; rapid scaling may cause disk full&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Controllable: Unified shared storage pool, uses local NVMe for P2P distributed cache&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;Network requirements&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Standard TCP&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Requires widely open P2P ports across nodes; may be invalid in cross‑VPC/NAT environments&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Standard LAN – only requires normal high‑bandwidth inter‑node LAN; no intrusive network requirements&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;Suitable scenarios&lt;/td&gt;
&lt;td style="text-align: left;"&gt;General workloads with no cold‑start requirements and small clusters (&amp;lt;20 nodes)&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Ultra‑large clusters across data centers / clouds / edge computing environments without unified high‑bandwidth storage; strong ops capabilities of the team&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Ultra-large clusters across data centers / clouds / edge computing environments without unified high-bandwidth storage, where JuiceFS is already deployed or can be deployed, aiming for unified image+model management and simplified ops&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2&gt;Runtime mechanism: how Nydus and JuiceFS coordinate&lt;/h2&gt;
&lt;h3&gt;Startup phase: fetching bootstrap (metadata)&lt;/h3&gt;
&lt;p&gt;When the application starts, &lt;code&gt;nydusd&lt;/code&gt; only needs to fetch the lightweight bootstrap file tree from the registry. The bootstrap describes the image file tree and block indexes, but contains no actual file content.  &lt;/p&gt;
&lt;p&gt;After the container root filesystem (rootfs) is mounted, the subsequent startup process proceeds. In our test scenarios, containers can be ready and pass health checks within hundreds of milliseconds, without transferring the full large image data before startup.&lt;/p&gt;
&lt;h3&gt;Read phase: on‑demand blob access&lt;/h3&gt;
&lt;p&gt;When the application process actually issues read operations (such as &lt;code&gt;open()&lt;/code&gt; or &lt;code&gt;read()&lt;/code&gt;), &lt;code&gt;nydusd&lt;/code&gt; captures the I/O requests via the Linux FUSE mechanism and locates the corresponding blob data block and offset using the bootstrap index.  &lt;/p&gt;
&lt;p&gt;This process is completely transparent to upper‑layer applications. For the underlying data path, the read granularity changes from full image layers to the data blocks corresponding to specific files and offsets. &lt;code&gt;nydusd&lt;/code&gt; directly accesses the JuiceFS mount point (for example, &lt;code&gt;/var/lib/nydus/blobs&lt;/code&gt;) to read the target block, completely eliminating the runtime fetch‑from‑registry path.&lt;/p&gt;
&lt;h3&gt;Cache phase: data reuse via JuiceFS cache groups&lt;/h3&gt;
&lt;p&gt;JuiceFS’ distributed cache groups can reuse already‑cached blob data across the cluster. On a cache hit, data is returned to the kernel at near‑local‑NVMe speed. On a cache miss, only the specified offset block is pulled on‑demand and automatically filled into the cache. In addition to the automatic fill‑on‑miss, blobs can be pre-loaded into the cache to ensure full cache hits during on‑demand reads.  &lt;/p&gt;
&lt;p&gt;For AI inference scenarios, the same mechanism can also be applied to loading model weight files.&lt;/p&gt;
&lt;h2&gt;Production test data&lt;/h2&gt;
&lt;p&gt;In production, we compared the solutions above against a large AI inference image.&lt;/p&gt;
&lt;h3&gt;Container startup time comparison&lt;/h3&gt;
&lt;p&gt;The table below shows the test results for container startup time:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style="text-align: left;"&gt;Scenario&lt;/th&gt;
&lt;th style="text-align: left;"&gt;OCI overlayfs&lt;/th&gt;
&lt;th style="text-align: left;"&gt;Nydus+JuiceFS&lt;/th&gt;
&lt;th style="text-align: left;"&gt;Comment&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;Cold pull + run&lt;/td&gt;
&lt;td style="text-align: left;"&gt;116 seconds&lt;/td&gt;
&lt;td style="text-align: left;"&gt;16 seconds&lt;/td&gt;
&lt;td style="text-align: left;"&gt;OCI uses public cloud registry; Nydus+JuiceFS uses JuiceFS + public cloud object storage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;Cold pull + run (with distributed cache warm-up)&lt;/td&gt;
&lt;td style="text-align: left;"&gt;N/A&lt;/td&gt;
&lt;td style="text-align: left;"&gt;~1.4 seconds&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Required blobs pre‑loaded in JuiceFS distributed cache&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;Warm pull + run&lt;/td&gt;
&lt;td style="text-align: left;"&gt;~0 seconds&lt;/td&gt;
&lt;td style="text-align: left;"&gt;0.22 seconds&lt;/td&gt;
&lt;td style="text-align: left;"&gt;OCI: same tag already on node; Nydus+JuiceFS: blobcache local cache&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;From the test results, we can see:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;7x speedup without cache warm-up:&lt;/strong&gt; When neither local nor distributed cache is warmed up, Nydus+JuiceFS reduces container startup time from 116s to 16s.  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;~99.9% reduction in data read volume during startup:&lt;/strong&gt; In the cold pull + run scenario, read volume drops from 11 GB to 11 MB. Traditional OCI requires full download and extraction before startup, while Nydus+JuiceFS only fetches bootstrap metadata and reads blobs actually accessed during startup.  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;1.4s startup with distributed cache warm-up:&lt;/strong&gt; When blobs are cached in JuiceFS distributed cache, startup takes 1.4s; with local &lt;code&gt;blobcache&lt;/code&gt; warmed up (warm pull + run), startup takes only 0.22s.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;On‑demand file read performance&lt;/h3&gt;
&lt;p&gt;The table below shows test results for: on-demand file read performance:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style="text-align: left;"&gt;Scenario&lt;/th&gt;
&lt;th style="text-align: left;"&gt;Traditional OCI (local disk direct read)&lt;/th&gt;
&lt;th style="text-align: left;"&gt;Nydus+JuiceFS (distributed cache hit)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;First‑block read latency (TTFB)&lt;/td&gt;
&lt;td style="text-align: left;"&gt;~0.9 milliseconds&lt;/td&gt;
&lt;td style="text-align: left;"&gt;~3.2 milliseconds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;Small file / scattered configuration loading (IOPS)&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Baseline&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Close to baseline&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;Large file sequential read throughput&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Local disk limit&lt;/td&gt;
&lt;td style="text-align: left;"&gt;GB/s level (JuiceFS NVMe distributed cache)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;From the test results, we can see:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Time to first byte (TTFB): On distributed cache hit, first‑block read latency is ~3.2 milliseconds, about 2.3 milliseconds higher than local disk direct read (0.9 milliseconds). The extra latency comes from the FUSE data path and cache access, but remains at millisecond level, generally imperceptible to the application side.  &lt;/li&gt;
&lt;li&gt;Small file IOPS: Performance is very close to local disk baseline. In scenarios with dense Python dependency and configuration file reads, JuiceFS caching introduces no noticeable IOPS bottleneck.  &lt;/li&gt;
&lt;li&gt;Large file sequential throughput: &lt;strong&gt;On cache hit, Nydus+JuiceFS achieves GB/s sequential read throughput&lt;/strong&gt;. Compared to traditional OCI, which is limited by single‑node local disk performance, JuiceFS can leverage NVMe distributed cache to provide high‑bandwidth data access.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Summary: combining on‑demand loading with shared cache&lt;/h3&gt;
&lt;p&gt;Nydus changes image loading from full pull to on‑demand reading, while JuiceFS places data blocks into a shared storage and distributed cache system. Together, they reduce container cold‑start time from 116s to 16s, and to ~1.4s with distributed cache warm-up; the data read volume during startup drops from 11 GB to 11 MB.  &lt;/p&gt;
&lt;p&gt;The value of this solution extends beyond just image startup acceleration. For AI inference scenarios, image blobs and model weights can be uniformly hosted by JuiceFS, sharing the same caching and prefetching mechanisms. During large‑scale scaling, distributed caching also reduces duplicate reads of the same data across many instances. This lessens concurrent pressure on the registry and backend storage.  &lt;/p&gt;
&lt;p&gt;In environments lacking shared storage, Dragonfly+Nydus is an excellent P2P alternative. However, in clusters that already have JuiceFS infrastructure, Nydus+JuiceFS delivers extreme image distribution and model loading acceleration with minimal operational overhead.  &lt;/p&gt;
&lt;p&gt;If you have any feedback on this article or ideas to share, we invite you to participate in the &lt;a href="https://github.com/juicedata/juicefs/discussions/"&gt;discussions on GitHub&lt;/a&gt; and join &lt;a href="http://go.juicefs.com/discord"&gt;our community on Discord&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;</description><pubDate>Fri, 09 Oct 2026 06:56:00 +0000</pubDate><guid>https://www.juicefs.com/en/blog/solutions/nydus-juicefs-ai-inference-container-image-acceleration</guid></item><item><title>JuiceFS Enterprise 5.4: From 100 Billion Files to 1 Million Clients</title><link>https://www.juicefs.com/en/blog/release-notes/juicefs-enterprise-5-4</link><description>&lt;div class="w-block-markdown block-markdown"&gt;&lt;p&gt;Following the support for 100-billion-file environments introduced in &lt;a href="https://juicefs.com/docs/cloud/"&gt;JuiceFS Enterprise Edition&lt;/a&gt; 5.3, v5.4 further improves JuiceFS across several dimensions for large-scale deployments. At this scale, even small per-operation overheads can add up to significant resource consumption. Once metadata is distributed across multiple zones, the system also needs to coordinate across nodes while maintaining performance, consistency, and stability.&lt;/p&gt;
&lt;p&gt;To address these challenges, &lt;a href="https://juicefs.com/docs/cloud/release#juicefs-543-2026922"&gt;JuiceFS Enterprise Edition 5.4&lt;/a&gt; introduces the following new capabilities and improvements:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Support for up to 1 million simultaneously mounted clients  &lt;/li&gt;
&lt;li&gt;Fast cloning of directories containing massive files  &lt;/li&gt;
&lt;li&gt;More than 90% RDMA bandwidth utilization  &lt;/li&gt;
&lt;li&gt;Up to 100% higher random-read performance under high concurrency  &lt;/li&gt;
&lt;li&gt;On-demand data synchronization for mirror file systems  &lt;/li&gt;
&lt;li&gt;More flexible caching strategies for a wider range of workloads  &lt;/li&gt;
&lt;li&gt;Multiple operational improvements for large-scale data&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Supporting 1 million clients&lt;/h2&gt;
&lt;p&gt;As &lt;a href="https://en.wikipedia.org/wiki/AI_agent"&gt;AI agents&lt;/a&gt; move toward large-scale deployment, the JuiceFS team faced a new challenge: &lt;strong&gt;supporting connections and concurrent access from up to 1 million clients on top of the metadata workload of a 100-billion-file file system.&lt;/strong&gt; The team spent months exploring and optimizing the architecture, and introduced this capability in JuiceFS 5.4.&lt;/p&gt;
&lt;p&gt;JuiceFS uses a &lt;a href="https://juicefs.com/docs/cloud/introduction/architecture"&gt;distributed architecture&lt;/a&gt; that partitions metadata across multiple metadata nodes, allowing metadata for hundreds of billions of files to be managed across multiple zones. To allow these nodes to handle a large number of client connections at the same time, v5.4 co-locates metadata nodes with network proxies, enabling clients to connect to any metadata node.&lt;/p&gt;
&lt;p&gt;The node that receives a request handles requests for its local partition directly. Requests involving other partitions are forwarded internally to the corresponding nodes. Multiple client sessions share the same physical connections between nodes, reducing the number of connections and the associated maintenance overhead.&lt;/p&gt;
&lt;p&gt;Connection reuse is only part of the challenge. Querying large numbers of client sessions, reporting session status, and cleaning up expired sessions can also introduce significant overhead.&lt;/p&gt;
&lt;p&gt;In v5.4, indexes are used to locate client sessions instead of scanning unrelated sessions. Paginated queries and sampled reporting reduce the overhead of session status management. Expired sessions are cleaned up in batches to prevent cleanup work from becoming concentrated in a single pass.&lt;/p&gt;
&lt;p&gt;With these optimizations, JuiceFS 5.4 successfully handled 1 million simultaneous client connections in stress tests. Previously, when clients connected separately to multiple metadata nodes, the total number of connections could reach tens of millions. &lt;strong&gt;After optimization, 10 internal proxy nodes handled 1 million client connections, while connection reuse reduced the number of physical backend connections from the proxies to the metadata leader to about 400. This significantly reduced connection-management pressure on the leader.&lt;/strong&gt;&lt;/p&gt;&lt;/div&gt;
&lt;div class="w-block-ImageWithCaption block-ImageWithCaption"&gt;&lt;dl&gt;
    &lt;dt&gt;image&lt;/dt&gt;
    &lt;dd&gt;1-million-client test architecture&lt;/dd&gt;
    &lt;dt&gt;caption&lt;/dt&gt;
    &lt;dd&gt;1-million-client test architecture&lt;/dd&gt;
&lt;/dl&gt;&lt;/div&gt;
&lt;div class="w-block-markdown block-markdown"&gt;&lt;h2&gt;Fast cloning for large directories&lt;/h2&gt;
&lt;p&gt;When creating branches of training data or preparing test environments, users often need an independently modifiable copy of a directory. As directory sizes grow, &lt;a href="https://juicefs.com/docs/cloud/guide/clone/"&gt;cloning&lt;/a&gt; becomes more complex: &lt;strong&gt;in a multi-zone architecture, the metadata for a single directory tree may span multiple metadata zones, so cloning must coordinate subtree operations across nodes while preserving the complete directory hierarchy.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;v5.4 introduces cross-zone directory cloning. It recursively processes subtrees while preserving the original cross-zone layout of the directory tree. Cloning only copies metadata. The underlying object data remains shared, so there is no need to copy it. Subsequent writes to the clone do not affect the source files.&lt;/p&gt;
&lt;p&gt;In a deployment with 30 metadata zones, cloning 100 million files took 1 minute and 40 seconds, &lt;strong&gt;averaging 1 million files per second&lt;/strong&gt;. More zones can provide greater parallelism, while actual performance also depends on metadata load and how the directory tree is distributed across zones.&lt;/p&gt;
&lt;p&gt;Note that cross-zone directory cloning is not atomic. If new data continues to be written to the source directory during cloning, different subtrees in the cloned directory may reflect the source directory at different points in time. If strict consistency is required, pause writes to the source directory before starting the clone.&lt;/p&gt;
&lt;h2&gt;Performance improvements&lt;/h2&gt;
&lt;h3&gt;More than 90% RDMA bandwidth utilization&lt;/h3&gt;
&lt;p&gt;Starting with JuiceFS 5.3, &lt;a href="https://juicefs.com/en/blog/release-notes/juicefs-enterprise-5-3-rdma-support#Support-for-RDMA:-increased-bandwidth-cap,-reduced-CPU-usage"&gt;clients can use RDMA&lt;/a&gt; to communicate with distributed cache nodes, reducing CPU overhead during data transfers and improving transfer efficiency. v5.4 further improves bandwidth utilization and transfer stability.&lt;/p&gt;
&lt;p&gt;In a test environment with a 400 Gbps RDMA NIC on the client and an 800 Gbps RDMA NIC on the distributed cache node, a single client achieved 45 GB/s of read throughput. A single distributed cache node delivered 90 GB/s of data throughput, with NIC utilization exceeding 90%.&lt;/p&gt;
&lt;h3&gt;Higher random-read IOPS under high concurrency&lt;/h3&gt;
&lt;p&gt;In multi-process training, HPC, and rendering scenarios, high-concurrency random reads can stress not only storage and network resources, but also client lock contention and request-processing overhead.&lt;/p&gt;
&lt;p&gt;Over the past six months, the JuiceFS team has continuously optimized high-concurrency random-read performance by simplifying frequently executed code paths and reducing lock contention.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;As a result, random-read IOPS has more than doubled overall compared with the previous implementation.&lt;/strong&gt; With distributed caching, a single client reached up to 189,000 IOPS. With local caching, a single client reached up to 156,000 IOPS.&lt;/p&gt;&lt;/div&gt;
&lt;div class="w-block-ImageWithCaption block-ImageWithCaption"&gt;&lt;dl&gt;
    &lt;dt&gt;image&lt;/dt&gt;
    &lt;dd&gt;Random-read IOPS comparison&lt;/dd&gt;
    &lt;dt&gt;caption&lt;/dt&gt;
    &lt;dd&gt;Random-read IOPS comparison&lt;/dd&gt;
&lt;/dl&gt;&lt;/div&gt;
&lt;div class="w-block-markdown block-markdown"&gt;&lt;p&gt;&lt;strong&gt;Test environment:&lt;/strong&gt; A dual-socket AMD server with 128 cores and 256 threads, 1 TB of DDR4 memory, a 100 Gbps NIC, and a 3.84 TB NVMe SSD used as the cache disk. The system ran Linux 5.14.&lt;/p&gt;
&lt;h2&gt;Optimizing data access across regions&lt;/h2&gt;
&lt;h3&gt;On-demand synchronization to reduce data replication&lt;/h3&gt;
&lt;p&gt;In multi-region, multi-provider, and multi-cluster compute environments, a JuiceFS &lt;a href="https://juicefs.com/docs/cloud/guide/mirror/"&gt;mirror file system&lt;/a&gt; can automatically synchronize files and directories from the source. Metadata is continuously synchronized to keep the directory structure and object versions up to date. Previously, object data was synchronized in full in the background by default.&lt;/p&gt;
&lt;p&gt;However, a workload in the mirror region may only need a subset of the models, datasets, or historical directories stored at the source. For example, if the source contains 10 PB of data but the mirror accesses only 1% of it, full synchronization would transfer and store a large amount of data that the workload never uses.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;v5.4 supports on-demand synchronization of object data for mirror file systems. When enabled, metadata continues to synchronize, while object data is no longer synchronized automatically in the background.&lt;/strong&gt; When a client reads data, JuiceFS first checks the object storage in the mirror region. If the data has not been synchronized yet, JuiceFS fetches it from the source and stores it in the mirror on demand. This reduces unnecessary data transfer and storage consumption.&lt;/p&gt;
&lt;p&gt;If an application requires local read performance on the first access, you can warm up the required data in advance. If a complete copy of the data is required, you can continue to use background synchronization.&lt;/p&gt;
&lt;h3&gt;Accelerating metadata access with read-only nodes&lt;/h3&gt;
&lt;p&gt;For workloads that only need to accelerate metadata access, &lt;strong&gt;v5.4 introduces a new mode that does not require creating a mirror file system&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Users can deploy read-only metadata service nodes in other regions to accelerate metadata reads for local clients. Clients continue to mount the source file system, while the acceleration nodes can scale dynamically to match access requirements.&lt;/p&gt;
&lt;h2&gt;More flexible cache management&lt;/h2&gt;
&lt;h3&gt;Improving hot-data cache hit rates&lt;/h3&gt;
&lt;p&gt;Data from one-time scans is often unlikely to be accessed again. Caching this data can evict hot data that is accessed repeatedly. By default, when a request misses the distributed cache, the cache node fetches the data from object storage and stores it in the cache. &lt;strong&gt;v5.4 introduces a new cache-aside mode.&lt;/strong&gt; When enabled, a cache miss causes the application node to read directly from object storage instead of filling the cache with the requested data.&lt;/p&gt;
&lt;h3&gt;Preserving cache hit rates when adding multiple cache nodes&lt;/h3&gt;
&lt;p&gt;When multiple cache nodes are added at once, read requests may be routed to new nodes that do not yet have the required data, triggering additional reads from object storage.&lt;/p&gt;
&lt;p&gt;v5.4 introduces the &lt;code&gt;--commission&lt;/code&gt; parameter. After a new node is enabled, it retains the node mapping from before scaling. If the data is not available in its local cache, the new node fetches it from the original node instead. This reduces reads from the source during cache scaling.&lt;/p&gt;
&lt;h3&gt;Reducing the number of files on large cache disks&lt;/h3&gt;
&lt;p&gt;On large-capacity cache disks, storing each cache block as a separate file can cause the number of files on the cache disk to grow continuously.&lt;/p&gt;
&lt;p&gt;The new merge-cache mode combines multiple cache blocks into larger files and stores their indexes separately. This significantly reduces the number of files that the cache disk needs to manage.&lt;/p&gt;
&lt;p&gt;This feature is currently available as a public beta.&lt;/p&gt;
&lt;h3&gt;Warming up specific byte ranges&lt;/h3&gt;
&lt;p&gt;If a workload reads only part of a large file, warming up the entire file consumes additional cache space and transfers unnecessary data.&lt;/p&gt;
&lt;p&gt;v5.4 allows you to specify one or more byte ranges to warm up. JuiceFS only warms up cache blocks that intersect those ranges, aligning cache preparation with the data the workload actually needs to read.&lt;/p&gt;
&lt;p&gt;This capability enables more precise warm-up for data formats such as Lance and Parquet.&lt;/p&gt;
&lt;h2&gt;Simplifying operations for massive files&lt;/h2&gt;
&lt;h3&gt;Restoring files by deletion time&lt;/h3&gt;
&lt;p&gt;When restoring files from the trash, users may know approximately when an accidental deletion occurred but have difficulty identifying the target files by name or keyword alone.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;restore&lt;/code&gt; command now supports the &lt;code&gt;start-time&lt;/code&gt; and &lt;code&gt;end-time&lt;/code&gt; parameters. In addition to the existing keyword filters, these parameters allow users to restrict the restore operation by file deletion time.&lt;/p&gt;
&lt;h3&gt;Reducing GC and &lt;code&gt;fsck&lt;/code&gt; memory usage&lt;/h3&gt;
&lt;p&gt;When checking large file systems, &lt;a href="https://en.wikipedia.org/wiki/Garbage_collection_computerscience"&gt;GC&lt;/a&gt; and &lt;code&gt;fsck&lt;/code&gt; need to process large numbers of records, and sorting can consume significant amounts of memory.&lt;/p&gt;
&lt;p&gt;v5.4 adds external sorting modes to both commands, using disk storage during sorting to reduce memory requirements. The external sorting mode for GC is available only with dry-run, allowing users to inspect and evaluate the operation without actually deleting data.&lt;/p&gt;
&lt;h3&gt;Restricting access with token allowlists&lt;/h3&gt;
&lt;p&gt;v5.4 supports access control through token allowlists. An allowlist can specify multiple first-level subdirectories under the root directory.&lt;/p&gt;
&lt;p&gt;Clients using the token can only access and modify content within those subdirectories, allowing different teams or workloads to be restricted to their designated data.&lt;/p&gt;
&lt;h2&gt;Summary: scale changes everything&lt;/h2&gt;
&lt;p&gt;JuiceFS 5.3 brought the platform into a new phase of scale. At the same time, the rapid development of AI continues to push the boundaries of data volume and system load.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;As file counts, client counts, and request volumes all reach new levels, performance, stability, consistency, and operational complexity are no longer independent concerns. They interact with one another and become increasingly difficult to manage as the system scales.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;v5.4 addresses these system-level engineering challenges across large-scale deployments, covering client connectivity, cross-zone directories, data access, mirror synchronization, and cache management. JuiceFS Cloud Service users can now try &lt;a href="https://juicefs.com/docs/cloud/release#juicefs-543-2026922"&gt;JuiceFS Enterprise Edition 5.4&lt;/a&gt; online. Users running on-premises deployments can contact the JuiceFS team for upgrade support.&lt;/p&gt;
&lt;p&gt;JuiceFS is used across a range of demanding workloads, including &lt;a href="https://en.wikipedia.org/wiki/Large_language_model"&gt;LLMs&lt;/a&gt; and multimodal models, autonomous driving, embodied AI, and quantitative investment. We’ll continue working with organizations at the forefront of these fields to improve JuiceFS and build infrastructure that can keep pace with their applications.&lt;/p&gt;
&lt;p&gt;If you have any feedback on this article or ideas to share, we invite you to participate in the &lt;a href="https://github.com/juicedata/juicefs/discussions/"&gt;discussions on GitHub&lt;/a&gt; and join &lt;a href="http://go.juicefs.com/discord"&gt;our community on Discord&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;</description><pubDate>Tue, 29 Sep 2026 15:07:00 +0000</pubDate><guid>https://www.juicefs.com/en/blog/release-notes/juicefs-enterprise-5-4</guid></item><item><title>Infinite Workspaces for AI Agents: A Practical Architecture with JuiceFS, SQLite, and Litestream</title><link>https://www.juicefs.com/en/blog/solutions/infinite-workspaces-ai-agent</link><description>&lt;div class="w-block-markdown block-markdown"&gt;&lt;p&gt;Most conversations about AI sandboxes start and end with boot speed and compute isolation: How fast does the container boot? Can the &lt;a href="https://en.wikipedia.org/wiki/AI_agent"&gt;agent&lt;/a&gt; run untrusted code safely? But these discussions miss a fundamental truth: an autonomous agent turns a fresh machine into a rambling digital workspace. It clones code repos, installs heavy &lt;code&gt;node_modules&lt;/code&gt; or Python virtual environments, downloads browser binaries, compiles artifacts, generates multi-gigabyte datasets, and writes massive trace logs.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;"The files are not incidental. They are the working memory of the task."&lt;/em&gt;&lt;br&gt;
&lt;em&gt;– Aniket Maurya, Founder @ Celesto AI&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The naive solution is to overprovision the root disk. However, determining the size of a boot disk before a task exposes its scope is an ineffective effort. A "quick bug fix" might require a full Next.js build chain, while a "data benchmark" might produce multi-gigabyte Parquet tables. Coupling system state to workspace state creates a bottleneck.&lt;/p&gt;
&lt;p&gt;Instead, an emerging architectural pattern is radical in its simplicity: decouple the system disk from the durable workspace. Provide a POSIX-compliant mount that acts like an infinite, persistent drive, backed entirely by affordable object storage. But how do you build such a system without introducing complex services that defeat the purpose of ephemeral sandboxes? Recently, we co-hosted &lt;a href="https://juicefs.com/en/events/juicefs-office-hours-13-petabyte-scale-storage-for-ai-agent-sandboxes"&gt;an Office Hours session&lt;/a&gt; with &lt;a href="https://celesto.ai/"&gt;Celesto AI&lt;/a&gt;, a platform building secure sandboxes for autonomous AI agents, and the webinar was a delightful exploration of exactly this challenge.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style="text-align: left;"&gt;Storage&lt;/th&gt;
&lt;th style="text-align: left;"&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;Root disk&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Operating system, runtime, package manager internals, and system-level state&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;Workspace&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Repositories, generated files, datasets, build artifacts, logs, and project state&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Here is the creative engineering stack making this possible: &lt;a href="https://juicefs.com/docs/community/introduction/"&gt;JuiceFS&lt;/a&gt; as the file system layer, SQLite as the embedded metadata engine, and Litestream as the durability glue.&lt;/p&gt;
&lt;h2&gt;The creative trio: JuiceFS + SQLite + Litestream&lt;/h2&gt;
&lt;p&gt;Object stores (S3, GCS) are excellent for storing files and performing key-based lookups, but they are terrible at listing directories, handling &lt;code&gt;stat&lt;/code&gt; calls, or managing millions of small files in batches (i.e., renaming a directory). You need a metadata engine to act as the "brain" of the file system, mapping paths to block locations.&lt;/p&gt;
&lt;p&gt;Usually, JuiceFS deployments use centralized or clustered metadata services, such as Redis, TiKV, or FoundationDB. For isolated AI sandboxes, a creative alternative leverages the three familiar JuiceFS components working in harmony:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;The &lt;strong&gt;JuiceFS client&lt;/strong&gt; provides the POSIX bridge. It is responsible for the complex task of communicating with both the metadata engine and the object store. It is the "worker" that reads and writes the actual data, as well as performs administrative tasks such as status checks and data compaction.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;SQLite&lt;/strong&gt; acts as the metadata engine. Instead of connecting to a remote metadata server, JuiceFS also supports using a local SQLite database file as its metadata store. This means the entire file system metadata (every inode, directory entry, and block pointer) lives inside a single, standard &lt;code&gt;.db&lt;/code&gt; file on the local disk.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Litestream&lt;/strong&gt; provides the durability backing for that SQLite file. Litestream continuously takes SQLite snapshots and streams the SQLite write-ahead log (WAL) frames to the same object store.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Here is the magic: When the sandbox is running, JuiceFS uses the local SQLite file to resolve &lt;code&gt;ls&lt;/code&gt;, &lt;code&gt;cd&lt;/code&gt;, and &lt;code&gt;read&lt;/code&gt; operations. The actual file blocks are already safe in the object store. (Although, the &lt;a href="https://litestream.io/reference/config/#replica-settings"&gt;&lt;code&gt;sync-interval&lt;/code&gt; configuration&lt;/a&gt; needs to be taken into consideration.) When the user stops the sandbox, the local SQLite file might be discarded, but Litestream has already replicated the metadata engine to the object store.&lt;/p&gt;&lt;/div&gt;
&lt;div class="w-block-ImageWithCaption block-ImageWithCaption"&gt;&lt;dl&gt;
    &lt;dt&gt;image&lt;/dt&gt;
    &lt;dd&gt;JuiceFS + SQLite + Litestream&lt;/dd&gt;
    &lt;dt&gt;caption&lt;/dt&gt;
    &lt;dd&gt;JuiceFS + SQLite + Litestream for AI agent workspaces&lt;/dd&gt;
&lt;/dl&gt;&lt;/div&gt;
&lt;div class="w-block-markdown block-markdown"&gt;&lt;p&gt;When the sandbox resumes on a fresh VM (or a different host entirely), the system simply downloads the latest SQLite snapshot from the object store and replays the WAL. Within seconds, the local SQLite can be fully reconstructed. JuiceFS mounts it, points back to the same object store blocks, and the agent is looking at the exact same workspace directory it left behind.&lt;/p&gt;
&lt;p&gt;The JuiceFS file system doesn't care which computer it runs on. But it does remember its folder structure and file pointers with the portable SQLite snapshots and WAL frames. With this setup, we turned the working memory of the AI agent into files and blocks in the object store, making it durable and accessible instead of locking it to a specific boot disk or block device.&lt;/p&gt;
&lt;h2&gt;An unconventional but effective combo&lt;/h2&gt;
&lt;p&gt;JuiceFS supports interchangeable metadata engines. Choosing SQLite + Litestream subverts the typical playbook by prioritizing simplicity and per-agent isolation over global scale. Here is why this particular stack fits the AI agent use case so well:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Easy to set up&lt;/strong&gt;: While it is not completely hands-off (you still manage the JuiceFS client, the local SQLite instance, and Litestream's replication configuration like Celesto AI does), this stack is drastically simpler to bootstrap than a distributed database cluster.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Per-agent isolation&lt;/strong&gt;: Each sandbox gets its own dedicated SQLite metadata file. This eliminates noisy-neighbor problems. Metadata contention simply does not happen across agents, because each one has its own independent "brain" living right next to its mount.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Performance that fits the scope&lt;/strong&gt;: A single agent workload typically produces tens of thousands to a few million files. SQLite handles this range comfortably with low latency and minimal resource footprint. While this approach obviously does not scale to the hundreds of billions of files that &lt;a href="https://juicefs.com/docs/cloud/"&gt;JuiceFS Enterprise Edition&lt;/a&gt; can manage globally, it falls squarely into the comfortable zone for individual agent workspaces.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Of course, this approach comes with important trade-offs and considerations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;No cross-agent sharing&lt;/strong&gt;: The file system is inherently tied to a single SQLite instance. Agents cannot mount and share the same workspace concurrently. If your use case requires collaborative access or shared datasets across sandboxes, you would need a different strategy.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Resume latency depends on object store speed&lt;/strong&gt;: When a sandbox resumes, the system must download the latest SQLite snapshot from the object store and replay the WAL frames. This adds noticeable startup time compared to a hot-mounted local disk. Tuning Litestream's &lt;code&gt;sync-interval&lt;/code&gt; involves a direct trade-off between durability guarantees and resume performance.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Single-writer limitation&lt;/strong&gt;: SQLite is fundamentally a single-writer database. Heavy parallel writes from multiple processes within the same sandbox can become a bottleneck. For autonomous agents following a largely sequential workflow, this limitation is rarely a practical issue. But it is worth keeping in mind for highly concurrent, multi-threaded agent designs.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The stack is not a universal solution. It is a deliberate, opinionated choice that trades global scalability and shared access for extreme simplicity and tight per-agent isolation. And for the AI sandbox use case, that trade-off often makes perfect sense.&lt;/p&gt;
&lt;h2&gt;The performance reality&lt;/h2&gt;
&lt;p&gt;This architecture is beautiful, but it isn't magic. You are trading local SSD latency for object storage durability and infinite scale. The benchmarks reveal a clear pattern:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Small files need attention: Writing 5,000 tiny 4 KiB files to an object-backed file system involves heavy metadata churn. Even with SQLite's fast local access, every &lt;code&gt;close()&lt;/code&gt; and &lt;code&gt;fsync()&lt;/code&gt; triggers WAL writes and Litestream replication. In these scenarios, the local root disk (ext4/XFS) will outperform the durable mount by a factor of 2x to 5x. See Celesto's &lt;a href="https://celesto.ai/blog/posts/platform/petabyte-scale-storage/#many-small-files"&gt;blog post&lt;/a&gt; for more details.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Large sequential workloads shine: For datasets, model checkpoints, build artifacts, and logs (files &amp;gt; 10 MB), the object-backed mount achieves upwards of 200 MiB/s, which is nearly 90% of the performance of the local disk. The background block uploads are streamed efficiently. See Celesto's &lt;a href="https://celesto.ai/blog/posts/platform/petabyte-scale-storage/#large-files"&gt;blog post&lt;/a&gt; for more details.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The golden rule for agents is to use the object-backed mount drive for durable, long-term state reports and large artifacts. Use the local ephemeral disk for high-churn, temporary scratch work that doesn't need to survive a restart. This hybrid approach gives you infinite capacity without sacrificing performance where it truly hurts.&lt;/p&gt;
&lt;h2&gt;Final thoughts&lt;/h2&gt;
&lt;p&gt;Cloudflare CFO Thomas Seifert recently predicted that within five years, non-human traffic could be as much as 1,000 times human traffic, making humans &lt;a href="https://www.theregister.com/networks/2026/08/07/humans-will-be-a-rounding-error-on-the-internet-says-cloudflare-exec/5284429"&gt;"a rounding error on the internet."&lt;/a&gt; He caveated that he's "called it wrong at every point along the way," but the direction is hard to dispute: AI and machine traffic already overtook human traffic in May 2026.&lt;/p&gt;&lt;/div&gt;
&lt;div class="w-block-ImageWithCaption block-ImageWithCaption"&gt;&lt;dl&gt;
    &lt;dt&gt;image&lt;/dt&gt;
    &lt;dd&gt;Cloudflare exec&lt;/dd&gt;
    &lt;dt&gt;caption&lt;/dt&gt;
    &lt;dd&gt;“Humans will be a rounding error on the internet” says Cloudflare exec&lt;/dd&gt;
&lt;/dl&gt;&lt;/div&gt;
&lt;div class="w-block-markdown block-markdown"&gt;&lt;p&gt;If that is true for network packets, it is likely true for storage as well.&lt;/p&gt;
&lt;p&gt;Every autonomous agent session produces a workspace. Multiply that by millions of agents running continuously, resuming, retrying, and branching. Human developers generate storage in bursts tied to working hours. Agents generate it constantly, at machine speed.&lt;/p&gt;
&lt;p&gt;This raises an uncomfortable question: if non-human consumers are about to dominate storage demand, are we designing for the right consumer? The combo of JuiceFS + SQLite + Litestream is one answer, but not the only one. Other approaches worth watching include object storage as the primary interface, shared metadata engine with concurrent access at agent scale (i.e., the JuiceFS Enterprise Edition), copy-on-write workspace snapshots, and &lt;a href="https://juicefs.com/en/blog/solutions/ai-agent-compare-agentfs-tigerfs-juicefs"&gt;many others&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Portable, shareable, scalable file storage for AI agents is still in its opening moves.&lt;/p&gt;
&lt;p&gt;If you have any feedback on this article or ideas to share, we invite you to participate in the &lt;a href="https://github.com/juicedata/juicefs/discussions/"&gt;discussions on GitHub&lt;/a&gt; and join &lt;a href="http://go.juicefs.com/discord"&gt;our community on Discord&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;</description><pubDate>Wed, 23 Sep 2026 05:23:00 +0000</pubDate><guid>https://www.juicefs.com/en/blog/solutions/infinite-workspaces-ai-agent</guid></item><item><title>Keeping GPUs Fed: How Meta's AI Storage Architecture Aligns with JuiceFS</title><link>https://www.juicefs.com/en/blog/engineering/meta-ai-storage-architecture</link><description>&lt;div class="w-block-markdown block-markdown"&gt;&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Recently, I came across an eye-opening &lt;a href="https://engineering.fb.com/2026/07/01/data-infrastructure/metas-ai-storage-blueprint-at-scale/"&gt;blog post&lt;/a&gt; and &lt;a href="https://www.youtube.com/watch?v=xc_BxLsijWA"&gt;presentation&lt;/a&gt; from Meta's engineering team detailing their AI storage blueprint at scale. Meta operates hundreds of exabyte-scale storage clusters serving everything from Facebook and Instagram to Meta AI.&lt;/p&gt;
&lt;p&gt;What caught my attention wasn't just the scale—it was the architecture. After years of wrestling with AI's brutal latency and throughput demands, Meta has converged on a clear pattern: &lt;strong&gt;data-metadata separation, rich client design, and comprehensive caching.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Here's the fascinating part: this blueprint isn't unique to Meta. &lt;a href="https://juicefs.com/docs/community/architecture"&gt;&lt;strong&gt;JuiceFS&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;shares these same first principles of design.&lt;/strong&gt; The hyperscaler's new construction closely resembles the cloud-native architecture that JuiceFS has advocated for years.&lt;/p&gt;
&lt;p&gt;In this post, I'll analyze both architectures, compare their core components, dive into their cross-region capabilities, and explain why this convergence in architecture makes the most sense for a distributed file system.&lt;/p&gt;
&lt;h2&gt;Why storage matters for AI workloads&lt;/h2&gt;
&lt;p&gt;Before diving into the architectures, it's worth understanding why storage has become such a critical component for AI infrastructure.&lt;/p&gt;
&lt;p&gt;Meta puts it succinctly: &lt;em&gt;"If AI is the brain, storage is the memory: capability and speed are highly dependent on the size of memory and speed of retrieval."&lt;/em&gt; Yet while AI compute performance has roughly tripled every two years, storage and interconnect performance growth have been far more modest. This disparity has made storage bottlenecks one of the primary contributors to GPU stalls for AI workloads, which is directly impacting both expenditures and time to market.&lt;/p&gt;&lt;/div&gt;
&lt;div class="w-block-ImageWithCaption block-ImageWithCaption"&gt;&lt;dl&gt;
    &lt;dt&gt;image&lt;/dt&gt;
    &lt;dd&gt;Dataloading across two GPUs&lt;/dd&gt;
    &lt;dt&gt;caption&lt;/dt&gt;
    &lt;dd&gt;Dataloading across two GPUs (Reference: Meta)&lt;/dd&gt;
&lt;/dl&gt;&lt;/div&gt;
&lt;div class="w-block-markdown block-markdown"&gt;&lt;p&gt;The math is brutal. During model training, hundreds of thousands of GPUs iterate over vast datasets across multiple epochs. GPUs synchronize their state periodically. If a single GPU stalls due to slow storage, it slows down the entire training job. In Meta's presentation, if GPUs were idle for about 20% of the time, &lt;em&gt;"that 20% stall means about tens of millions of dollars loss every hour"&lt;/em&gt; for a data center the size of Manhattan.&lt;/p&gt;
&lt;p&gt;Beyond the direct dollar cost, there is an even more consequential dimension: opportunity cost. The AI industry is moving at an unprecedented pace. Major model releases, which took roughly 104 weeks between 2020 and 2022, have now been compressed to approximately 4-week cycles by 2026. Every week of delay in shipping a frontier model translates to lost market share, diminished competitive advantage, and missed revenue opportunities.&lt;/p&gt;
&lt;p&gt;In short, storage is what makes the difference between a model shipping in weeks versus months and between a billion-dollar data center running at 80% versus 100% efficiency.&lt;/p&gt;
&lt;h2&gt;Meta's AI storage blueprint: the evolved architecture&lt;/h2&gt;
&lt;p&gt;After iterating on their storage infrastructure, Meta has arrived at a definitive architectural blueprint to solve the GPU stall problem at its root while continuing to support existing external and internal products. The training stack has been gradually migrating to the BLOB-storage interface. The motivation is more about performance: AI workloads demand predictable, bounded pMax latency. Traditional layered metadata lookups could add hundreds of milliseconds per request, stalling GPUs during training. By moving to a BLOB-centric interface, Meta leverages flash drives to deliver the low, predictable latencies required to keep thousands of GPUs productive.&lt;/p&gt;
&lt;h3&gt;The three-component architecture&lt;/h3&gt;
&lt;p&gt;The diagram below illustrates the request flow for Meta's BLOB storage &lt;code&gt;getObject&lt;/code&gt; API and shows the system's three major components.&lt;/p&gt;&lt;/div&gt;
&lt;div class="w-block-ImageWithCaption block-ImageWithCaption"&gt;&lt;dl&gt;
    &lt;dt&gt;image&lt;/dt&gt;
    &lt;dd&gt;BLOB storage getObject request flow&lt;/dd&gt;
    &lt;dt&gt;caption&lt;/dt&gt;
    &lt;dd&gt;BLOB storage getObject request flow (Reference: Meta)&lt;/dd&gt;
&lt;/dl&gt;&lt;/div&gt;
&lt;div class="w-block-markdown block-markdown"&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;The Tectonic data storage&lt;/strong&gt;: At the foundation sits Tectonic, a regional, multi-tenant storage fabric providing high durability and availability through erasure coding. It supports tiering across HDDs and flash drives, intelligently managing hot, cold, and warm data placement.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;The BLOB server and metadata layer&lt;/strong&gt;: Operating on top of Tectonic, the BLOB layer handles API requests, stores metadata, and exposes a global, infinitely scalable storage fabric with policies allowing users to trade off between durability and availability, abstracting away the complexity of the underlying block storage.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;The rich client SDK&lt;/strong&gt;: Meta eliminated the data-plane proxy and built a rich client SDK with a Tectonic BlockClient embedded within it, enabling direct data reading from Tectonic storage servers to clients. The client also implements hedged reads and dynamic concurrency control to reduce tail latencies.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To maximize cache efficiency, Meta also leverages spare memory on GPU hosts as a distributed data cache by integrating peers from the Owl subsystem directly into the BLOB-storage client SDK, which yields an average cache hit rate of 80%.&lt;/p&gt;
&lt;h3&gt;Cross-region data access with tiered caching&lt;/h3&gt;
&lt;p&gt;Meta's cross-region approach treats storage as a global data lake, but with tiered caches accelerating access across geographical boundaries.&lt;/p&gt;&lt;/div&gt;
&lt;div class="w-block-ImageWithCaption block-ImageWithCaption"&gt;&lt;dl&gt;
    &lt;dt&gt;image&lt;/dt&gt;
    &lt;dd&gt;Cross-region data access with multi-tier caching&lt;/dd&gt;
    &lt;dt&gt;caption&lt;/dt&gt;
    &lt;dd&gt;Cross-region data access with multi-tier caching (Reference: Meta)&lt;/dd&gt;
&lt;/dl&gt;&lt;/div&gt;
&lt;div class="w-block-markdown block-markdown"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style="text-align: left;"&gt;Cache Tier&lt;/th&gt;
&lt;th style="text-align: left;"&gt;Location&lt;/th&gt;
&lt;th style="text-align: left;"&gt;Role&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;L1 Cache&lt;/td&gt;
&lt;td style="text-align: left;"&gt;GPU host memory (RAM)&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Hottest, most frequently accessed data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;L2 Cache&lt;/td&gt;
&lt;td style="text-align: left;"&gt;GPU host flash (SSD)&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Local flash tier for warm data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;L3 Cache&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Regional flash-based BLOB storage&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Regional cache before falling back to global BLOB storage&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The results speak for themselves: average ingestion time dropped by 93%, and worst-case ingestion time dropped by 97%. This is what it looks like when storage stops being the bottleneck and starts enabling AI research velocity.&lt;/p&gt;
&lt;h2&gt;JuiceFS: cloud-native, AI-native from day one&lt;/h2&gt;
&lt;p&gt;For readers already familiar with JuiceFS, the parallels to Meta's design are immediately apparent. The architecture Meta converged upon after years of iteration shares the same core principles that have guided JuiceFS from day one.&lt;/p&gt;
&lt;p&gt;JuiceFS was architected from the ground up on the data-metadata separation principle, which also consists of three core components:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Object storage&lt;/strong&gt;: JuiceFS uses object storage as the reliable, scalable backend for actual data storage. It supports all major public cloud offerings (AWS S3, Alibaba OSS, Google Cloud Storage, etc.) as well as self-hosted solutions like Ceph and MinIO. This layer ensures that AI datasets, which can be as large as petabytes or exabytes, are safe, accessible, and can grow almost without limit.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Metadata engine&lt;/strong&gt;: The metadata engine stores all file system metadata, including file names, sizes, permissions, directory structures, and the mapping between files and their underlying data blocks. JuiceFS supports multiple engine options, including Redis, MySQL, PostgreSQL, TiKV, and many others. For extremely large-scale deployments, &lt;a href="https://juicefs.com/docs/cloud/"&gt;JuiceFS Enterprise Edition&lt;/a&gt; offers a proprietary Raft-based distributed metadata engine that provides high availability and strong consistency across multiple nodes.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;JuiceFS client&lt;/strong&gt;: The client handles all file I/O logic, including data slicing, merging, caching, and POSIX semantics enforcement. It communicates with both the metadata engine and object storage directly, coordinating reads and writes intelligently.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cross-region strategy: mirrors and replication&lt;/h3&gt;
&lt;p&gt;The JuiceFS Enterprise Edition also provides a native approach to support cross-region and cross-cloud data access:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://juicefs.com/docs/cloud/guide/mirror/"&gt;&lt;strong&gt;Mirror file systems&lt;/strong&gt;&lt;/a&gt;: Deploy a full metadata cluster and optionally an object storage replica in a mirror region. Metadata syncs automatically from the source region with approximately 1-second latency under normal network conditions.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://juicefs.com/docs/cloud/guide/replication/"&gt;&lt;strong&gt;Async data replication&lt;/strong&gt;&lt;/a&gt;: JuiceFS supports cross-region and cross-cloud asynchronous replication with a one-to-many topology. Data written in the primary region is replicated to multiple mirror regions in the background, enabling global datasets without manual copying.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://juicefs.com/docs/cloud/guide/distributed-cache/"&gt;&lt;strong&gt;Distributed cache&lt;/strong&gt;&lt;/a&gt;: JuiceFS clients on mounting hosts can form a distributed cache group using a consistent hashing ring, sharing cached data blocks with one another. This is particularly effective for model training, where datasets are repeatedly accessed across GPU nodes.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Smart read strategy&lt;/strong&gt;: Clients preferentially read from the local region. If the data isn't fully synced yet, they seamlessly fall back to the source region.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;
&lt;div class="w-block-ImageWithCaption block-ImageWithCaption"&gt;&lt;dl&gt;
    &lt;dt&gt;image&lt;/dt&gt;
    &lt;dd&gt;JuiceFS mirror file system architecture&lt;/dd&gt;
    &lt;dt&gt;caption&lt;/dt&gt;
    &lt;dd&gt;JuiceFS Enterprise Edition mirror file system&lt;/dd&gt;
&lt;/dl&gt;&lt;/div&gt;
&lt;div class="w-block-markdown block-markdown"&gt;&lt;p&gt;This design resonates with Meta's global data lake + tiered cache approach but offers a more flexible, cloud-native model that works across public clouds, private data centers, and hybrid environments.&lt;/p&gt;
&lt;h2&gt;Architectural similarities&lt;/h2&gt;
&lt;p&gt;On the surface, Meta mainly exposes a BLOB-style interface, while JuiceFS primarily provides a POSIX file system. Yet beneath these protocol differences, the architectural parallels are noteworthy. Both systems converged on the same three-component design with comprehensive caching and cross-region capabilities:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style="text-align: left;"&gt;Dimension&lt;/th&gt;
&lt;th style="text-align: left;"&gt;Meta's BLOB-Storage&lt;/th&gt;
&lt;th style="text-align: left;"&gt;JuiceFS&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;&lt;strong&gt;Data storage layer&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Tectonic: regional block storage fabric with erasure coding, tiering across HDDs and flash&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Object storage: S3, OSS, GCS, Ceph, MinIO, and others&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;&lt;strong&gt;Metadata layer&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Unified metadata scheme backed by ZippyDB with O(1) chunk lookups&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Metadata engine: Redis, MySQL, PostgreSQL, TiKV, JuiceFS Enterprise Edition&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;&lt;strong&gt;Rich client&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;"Fat client SDK" with embedded Tectonic BlockClient, streaming directly from storage servers&lt;/td&gt;
&lt;td style="text-align: left;"&gt;JuiceFS client: handles all I/O logic, slicing, merging, caching; supports FUSE, POSIX, Hadoop SDK, CSI, S3 Gateway&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;&lt;strong&gt;Distributed cache&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Tiered caching layers&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Memory + local cache + distributed cache group&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;&lt;strong&gt;Cross-region&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Tiered caching with global BLOB storage data lakes&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Primary region + mirror file systems&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;A concrete example: explicit cache hydration&lt;/h3&gt;
&lt;p&gt;One interesting example is how both systems handle proactive cache hydration, which is the practice of loading data into the cache before it's actually needed.&lt;/p&gt;
&lt;p&gt;Meta exposes a &lt;code&gt;prefetch()&lt;/code&gt; API through the BLOB-storage SDK, while JuiceFS provides a &lt;a href="https://juicefs.com/docs/cloud/reference/command_reference/#warmup"&gt;&lt;code&gt;warmup&lt;/code&gt; &lt;/a&gt; subcommand. Both serve the same purpose: allowing the client side to signal to the storage system exactly which data will be needed in the near future so it can be preloaded into cache before the GPU finishes its current work.&lt;/p&gt;
&lt;p&gt;This is especially critical in distributed training, where thousands of GPUs may simultaneously read the same dataset. Without cache hydration, the initial requests would have to read from the underlying storage (Tectonic for BLOB and object store for JuiceFS) with higher latency. With &lt;code&gt;prefetch()&lt;/code&gt; or &lt;code&gt;juicefs warmup&lt;/code&gt;, data is staged in the distributed cache before the GPUs need it. In essence, both systems recognize the limitations of network-based storage and passive caching, and they both provide explicit prefetching as an important tool to compensate for what the storage layer alone cannot guarantee.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Meta's AI storage blueprint is a testament to the architectural patterns that emerge when a hyperscaler evolves its data infrastructure to hundreds of exabytes. After years of iteration, they arrived at a design that's similar to what JuiceFS has championed from day one: data-metadata separation, a rich client that handles I/O logic directly, tiered caching, and cross-region capabilities.&lt;/p&gt;
&lt;p&gt;The same architectural pattern is also available to teams of any size. JuiceFS brought it into the big data era and now brings it into the AI age, with the flexibility of multi-cloud cross-region strategies, distributed caching, and a rich ecosystem of access protocols.&lt;/p&gt;
&lt;p&gt;Hopefully, storage is no longer the bottleneck in your AI training stack. At least, it doesn't have to be.&lt;/p&gt;
&lt;p&gt;If you have any feedback on this article or ideas to share, we invite you to participate in the &lt;a href="https://github.com/juicedata/juicefs/discussions/"&gt;discussions on GitHub&lt;/a&gt; and join &lt;a href="http://go.juicefs.com/discord"&gt;our community on Discord&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;</description><pubDate>Thu, 17 Sep 2026 03:32:00 +0000</pubDate><guid>https://www.juicefs.com/en/blog/engineering/meta-ai-storage-architecture</guid></item><item><title>Everything Is a File for Agents: Hello Uses JuiceFS to Build Stateful AI Workspaces</title><link>https://www.juicefs.com/en/blog/user-stories/hello-builds-stateful-ai-workspace-with-juicefs</link><description>&lt;div class="w-block-markdown block-markdown"&gt;&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Hello_(Chinese_company)"&gt;Hello&lt;/a&gt; is a Chinese mobility and technology company, offering car-pooling, car-hailing, battery swapping, shared bike, e-bike, and e-scooter rental services. We have 800 million+ registered users.&lt;/p&gt;
&lt;p&gt;As our AI business continues to grow, we need to support multiple workloads simultaneously, including model training, data processing, and AI agents. To address issues such as data fragmentation, inconsistent access methods, and complex cross-cloud data flows caused by multiple storage systems, we introduced &lt;a href="https://juicefs.com/docs/community/introduction/"&gt;JuiceFS&lt;/a&gt; (an open-source, high-performance distributed file system) in production to build a unified file data foundation that connects Notebook, training, evaluation, and agent environments.&lt;/p&gt;
&lt;p&gt;Among these workloads, agents have become an important application type and are already used in several real-world application scenarios. We’ve also deployed an internal personal agent for employees. Unlike training workloads, which primarily focus on high-performance I/O and access to massive numbers of files, agents place greater emphasis on data movement during task execution, state persistence, and the accumulation of results.&lt;/p&gt;
&lt;p&gt;This article focuses on how we use JuiceFS to persist user profiles, conversations, memories, skills, execution traces, and application artifacts, and how a shared workspace decouples agent state from compute Pods.&lt;/p&gt;
&lt;h2&gt;Hello's AI infrastructure and storage landscape&lt;/h2&gt;
&lt;p&gt;Our business scenarios are diverse, including customer service, review, scheduling, analytics, and broadcasting. To support AI applications across these businesses, we’ve progressively built an AI platform and a &lt;a href="https://en.wikipedia.org/wiki/Large_language_model"&gt;large language model&lt;/a&gt; (LLM) platform covering model development, training, inference, and serving.&lt;br&gt;
The AI platform supports scenarios including Notebook, training, offline inference, online inference, and image building. Notebook environments need to mount user directories and datasets. Training and inference jobs need to access input data, models, and intermediate results. The image-building process also generates reusable caches.&lt;/p&gt;
&lt;p&gt;The LLM platform aggregates different model services and provides model invocation and benchmarking capabilities. The data and reports generated during model benchmarking also need to be persistently stored.&lt;/p&gt;
&lt;p&gt;For different types of data and workloads, we primarily use three types of storage:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;CPFS&lt;/strong&gt; provides high-performance parallel storage.  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;JuiceFS serves as the shared file storage foundation for the platform. It supports data requiring &lt;a href="https://wiki.gentoo.org/wiki/POSIX"&gt;POSIX&lt;/a&gt; semantics, multi-node sharing, and a unified namespace, including Notebook environments, task datasets, model benchmarking reports, and image build caches.&lt;/strong&gt;  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Object storage&lt;/strong&gt; is mainly used for object data such as multimedia attachments.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A small number of directories on development machines are still used as a transitional solution and have not yet been migrated to the unified storage system.&lt;/p&gt;
&lt;p&gt;Overall, this storage architecture already covers the data persistence and cross-environment sharing requirements of our AI platform.&lt;/p&gt;&lt;/div&gt;
&lt;div class="w-block-ImageWithCaption block-ImageWithCaption"&gt;&lt;dl&gt;
    &lt;dt&gt;image&lt;/dt&gt;
    &lt;dd&gt;Hello&amp;#x27;s AI infrastructure&lt;/dd&gt;
    &lt;dt&gt;caption&lt;/dt&gt;
    &lt;dd&gt;Storage architecture in Hello&amp;#x27;s AI infrastructure&lt;/dd&gt;
&lt;/dl&gt;&lt;/div&gt;
&lt;div class="w-block-markdown block-markdown"&gt;&lt;h2&gt;New storage requirements introduced by agent workloads&lt;/h2&gt;
&lt;p&gt;As agents have gradually moved into production, our AI capabilities have expanded beyond model development, training, and inference to agents capable of invoking tools and completing application workflows.&lt;br&gt;
Related applications include image review for two-wheeled vehicle operations and trip recording review for ride-sharing services. These applications have delivered practical results by expanding review coverage, reducing manual effort, and lowering service costs.&lt;br&gt;
Building on the deployment of vertical agents, we further introduced Jarvis Claw, a personal agent for employees. Employees can interact with Jarvis Claw through DingTalk or the web. By combining capabilities such as long-term memory, skills, Model Context Protocol (MCP), and Cron, it can assist with tasks such as answering questions, generating reports, reviewing content, and performing analysis.&lt;/p&gt;
&lt;p&gt;Unlike vertical agents designed for a single application workflow, a personal agent needs to preserve state across multiple rounds of interaction and continuous tasks.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;In an IT support scenario, Jarvis Claw needs to preserve user requests, attachments, conversations, knowledge retrieval results, and tool invocation results.  &lt;/li&gt;
&lt;li&gt;In an operations reporting scenario, it needs to continuously access historical source tables and scripts while generating new data tables, charts, and reports.  &lt;/li&gt;
&lt;li&gt;In an operations attribution scenario, it also needs to preserve data extraction scripts, intermediate data, and final analysis results for later inspection and re-execution.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A long-running agent needs to preserve five types of data:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;User profiles and behavioral configurations  &lt;/li&gt;
&lt;li&gt;Conversation history and runtime state  &lt;/li&gt;
&lt;li&gt;Long-term memory that can be reused across conversations  &lt;/li&gt;
&lt;li&gt;Skills, MCP servers, channel configurations, and scheduled task configurations  &lt;/li&gt;
&lt;li&gt;Application artifacts such as scripts, CSV files, Excel spreadsheets, charts, and reports&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These states naturally take the form of files:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Profiles are stored as Markdown files.  &lt;/li&gt;
&lt;li&gt;Conversation history is stored in SQLite.  &lt;/li&gt;
&lt;li&gt;Skills consist of directories and scripts.  &lt;/li&gt;
&lt;li&gt;Task configurations use JSON.  &lt;/li&gt;
&lt;li&gt;Application results exist as ordinary files such as data tables, charts, and code.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The complete state of an agent ultimately consists of a continuously evolving collection of files and directories that are created, modified, and related to one another.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;A long-running agent therefore requires a unified shared storage layer that supports POSIX semantics, SQLite write-ahead logging (WAL), atomic rename operations, and access to large numbers of small files. It must also allow multiple Pods to share the same user state. Even if a compute Pod is destroyed, recreated, or rescheduled, the user's profile, conversations, memories, and task artifacts must remain available.&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;How JuiceFS stores the complete state of an agent&lt;/h2&gt;
&lt;p&gt;To meet these requirements, we extended our existing JuiceFS-based shared file storage foundation to agent workloads and use it to store a complete workspace for each user.&lt;/p&gt;
&lt;p&gt;The platform assigns each employee an independent Jarvis Claw directory based on the employee account. The directory structure is similar to:&lt;/p&gt;
&lt;pre class="codehilite"&gt;&lt;code&gt;/userdata/aiplatform-jarvis-claw/user/&amp;lt;staff_id&amp;gt;/data/workspace
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The user's profile, conversations, memories, skills, task configurations, and application artifacts are all stored in this directory. The Jarvis Claw Pod is responsible only for computation.&lt;/p&gt;
&lt;p&gt;When a Pod is destroyed, recreated, or rescheduled, it only needs to remount the existing workspace to continue using the previous state. This makes the agent stateful while keeping the compute Pods stateless.&lt;/p&gt;
&lt;h3&gt;What agent state is stored in the workspace?&lt;/h3&gt;
&lt;p&gt;The workspace contains profile files such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;AGENTS.md&lt;/code&gt;  &lt;/li&gt;
&lt;li&gt;&lt;code&gt;SOUL.md&lt;/code&gt;  &lt;/li&gt;
&lt;li&gt;&lt;code&gt;PROFILE.md&lt;/code&gt;  &lt;/li&gt;
&lt;li&gt;&lt;code&gt;HEARTBEAT.md&lt;/code&gt;  &lt;/li&gt;
&lt;li&gt;&lt;code&gt;MEMORY.md&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These files describe the agent's identity, behavior, and user preferences and are combined into the system prompt.&lt;/p&gt;
&lt;p&gt;Conversation and runtime state are primarily stored in files and directories such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;sessions/&lt;/code&gt;  &lt;/li&gt;
&lt;li&gt;&lt;code&gt;transcripts/&lt;/code&gt;  &lt;/li&gt;
&lt;li&gt;&lt;code&gt;dialog/&lt;/code&gt;  &lt;/li&gt;
&lt;li&gt;&lt;code&gt;tool_results/&lt;/code&gt;  &lt;/li&gt;
&lt;li&gt;&lt;code&gt;history.db&lt;/code&gt;  &lt;/li&gt;
&lt;li&gt;&lt;code&gt;chats.json&lt;/code&gt;  &lt;/li&gt;
&lt;li&gt;&lt;code&gt;inbox_events.json&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;history.db&lt;/code&gt; uses SQLite and also generates WAL and SHM files.&lt;br&gt;
User messages are written to &lt;code&gt;transcripts/&lt;/code&gt; at the beginning of a task. Even if the task is interrupted later, the conversation content generated before the interruption is preserved.&lt;br&gt;
Long-term memory is stored in directories such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;memory/&lt;/code&gt;  &lt;/li&gt;
&lt;li&gt;&lt;code&gt;digest/&lt;/code&gt;  &lt;/li&gt;
&lt;li&gt;&lt;code&gt;mem_agent/&lt;/code&gt;  &lt;/li&gt;
&lt;li&gt;&lt;code&gt;mem_session/&lt;/code&gt;  &lt;/li&gt;
&lt;li&gt;&lt;code&gt;mem_metadata/&lt;/code&gt;  &lt;/li&gt;
&lt;li&gt;&lt;code&gt;resource/&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Jarvis Claw manages memory using ReMe and a Memory-as-File approach.&lt;br&gt;
Some memory is written directly by the agent during execution. Another part is generated by periodically reviewing historical conversations, extracting user preferences and information that remains useful over time, and writing the results to directories such as &lt;code&gt;digest/&lt;/code&gt;. Internally, this process is referred to as Dream.&lt;br&gt;
The workspace also stores task and capability configurations, including:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;cron_jobs.json&lt;/code&gt;  &lt;/li&gt;
&lt;li&gt;&lt;code&gt;cron_runs/&lt;/code&gt;  &lt;/li&gt;
&lt;li&gt;&lt;code&gt;mcp.json&lt;/code&gt;  &lt;/li&gt;
&lt;li&gt;&lt;code&gt;channels.json&lt;/code&gt;  &lt;/li&gt;
&lt;li&gt;&lt;code&gt;dingtalk_webhooks.json&lt;/code&gt;  &lt;/li&gt;
&lt;li&gt;&lt;code&gt;skills/&lt;/code&gt;  &lt;/li&gt;
&lt;li&gt;&lt;code&gt;skill.json&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Skill packages are stored as ZIP files in object storage. When a Pod starts, they are downloaded and extracted into the user's workspace.&lt;br&gt;
Scripts, data tables, charts, and reports generated by the agent are stored in directories such as &lt;code&gt;output/&lt;/code&gt; and &lt;code&gt;scripts/&lt;/code&gt;, as well as in files including Excel spreadsheets, CSV files, and SVG images.&lt;/p&gt;
&lt;p&gt;The actual workspace also contains auxiliary content such as browser data, backups, and migration files.&lt;/p&gt;
&lt;p&gt;Together, these files and directories form the complete state of an agent and are continuously created, modified, and accumulated as tasks are executed.&lt;/p&gt;
&lt;h3&gt;How a unified file system supports data movement and operations&lt;/h3&gt;
&lt;p&gt;Storing agent workspaces in JuiceFS not only provides state persistence and storage-compute separation, but also allows agents to share the same file system with environments such as Notebook, training, and evaluation.&lt;/p&gt;
&lt;p&gt;When permissions allow it, Notebook can directly access an agent's workspace. Data prepared in Notebook can be directly provided to an agent. Likewise, data tables and scripts generated by an agent can be reused for analysis or evaluation without repeatedly uploading or copying data between different systems.&lt;/p&gt;
&lt;p&gt;Operational tasks such as inspection, migration, backup, and per-user storage usage analysis can also be performed using standard tools such as &lt;code&gt;ls&lt;/code&gt;, &lt;code&gt;du&lt;/code&gt;, and &lt;code&gt;rsync&lt;/code&gt;. Engineers can directly inspect conversations, memories, configurations, and task artifacts to troubleshoot issues during execution.&lt;/p&gt;
&lt;p&gt;However, as the workspace evolves from an ordinary data directory into a working environment that an agent can actively read from, write to, and execute scripts within, the platform must provide not only file persistence and sharing, but also appropriate access controls and execution boundaries.&lt;/p&gt;
&lt;h2&gt;Security boundaries for shared workspaces&lt;/h2&gt;
&lt;p&gt;An agent may not only read and modify files in its workspace, but also execute commands or code through Shell, MCP, and REPL. Without effective constraints, its access could extend beyond the user's workspace to other users' data, service source code, and sensitive files inside the container.&lt;/p&gt;
&lt;p&gt;Therefore, we established security boundaries across four layers:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;User data isolation  &lt;/li&gt;
&lt;li&gt;Tool invocation governance  &lt;/li&gt;
&lt;li&gt;File access control  &lt;/li&gt;
&lt;li&gt;Subprocess management&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;How different users' data is isolated&lt;/h3&gt;
&lt;p&gt;We manage file system permissions through JuiceFS and OpenACL, assigning each user an independent workspace and controlling the directories that different users are allowed to mount and access.&lt;/p&gt;
&lt;p&gt;With this mechanism, each agent can access only the workspace for which it has been authorized and cannot read other users' data.&lt;/p&gt;
&lt;p&gt;File system permissions provide the basic data boundary between users, but they cannot cover all access behavior generated when an agent executes tools and code inside a container. Therefore, in addition to user-level permissions, the platform also needs to further restrict tool invocations and their execution environments.&lt;/p&gt;
&lt;h3&gt;How the system determines whether a tool invocation is allowed&lt;/h3&gt;
&lt;p&gt;When the model decides to invoke a tool, the operation is not executed immediately. Instead, the governance layer first evaluates the operation through &lt;code&gt;assert_policy()&lt;/code&gt;.&lt;br&gt;
The result falls into one of four categories:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ALLOW&lt;/code&gt;: Allow the operation.  &lt;/li&gt;
&lt;li&gt;&lt;code&gt;DENY&lt;/code&gt;: Reject unknown tools and dangerous operations such as &lt;code&gt;sudo&lt;/code&gt;.  &lt;/li&gt;
&lt;li&gt;&lt;code&gt;ASK&lt;/code&gt;: Request manual approval.  &lt;/li&gt;
&lt;li&gt;&lt;code&gt;SANDBOX_FALLBACK&lt;/code&gt;: Execute the operation in a sandbox environment.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When manual approval is required, the system sends an approval request to the frontend through a side channel. After the user approves the request, a generalized version of the rule can be written to &lt;code&gt;policy.yaml&lt;/code&gt; so that similar future invocations can reuse it.&lt;br&gt;
For Shell operations, &lt;code&gt;execute_shell_command()&lt;/code&gt; fixes the current working directory to the user's workspace rather than the service source directory. Then, it selects the appropriate sandbox configuration based on the governance result. The configuration prioritizes dynamically generated fine-grained rules from the governance layer, followed by globally configured default rules registered when the service starts. Bare-process execution is allowed only in local development environments. This layer determines whether a tool invocation is allowed to execute. For approved operations, the platform must further restrict the files that can actually be accessed based on the execution method.&lt;/p&gt;
&lt;h3&gt;How file access permissions are restricted for the main process and subprocesses&lt;/h3&gt;
&lt;p&gt;Agents access files mainly in two ways, which require different control mechanisms.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;File tools such as &lt;code&gt;read_file&lt;/code&gt;, &lt;code&gt;write_file&lt;/code&gt;, &lt;code&gt;edit&lt;/code&gt;, &lt;code&gt;grep&lt;/code&gt;, &lt;code&gt;glob&lt;/code&gt;, and &lt;code&gt;view_image&lt;/code&gt; run directly inside the main service process and do not create subprocesses.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;As a result, they cannot be intercepted by bubblewrap. The system uses application-level path checks, such as &lt;code&gt;is_protected_path()&lt;/code&gt;, to constrain relative paths to the user's workspace while blocking access to protected locations such as &lt;code&gt;/app&lt;/code&gt;, which contains service source code and installation files. Protected entries are also filtered during directory listing.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Shell commands, stdio MCP servers, and REPL environments used to execute model-generated code, on the other hand, create subprocesses.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;For these operations, application-level path checks alone cannot establish a complete security boundary. Therefore, the system uses bubblewrap and Linux mount namespaces to construct an isolated file system view for subprocesses.&lt;/p&gt;
&lt;p&gt;Within this restricted view:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The user's workspace is mounted with read and write access.  &lt;/li&gt;
&lt;li&gt;Other approved paths are exposed according to policy rules.  &lt;/li&gt;
&lt;li&gt;Service source directories such as &lt;code&gt;/app&lt;/code&gt; are hidden or mounted as read-only.  &lt;/li&gt;
&lt;li&gt;Sensitive paths such as &lt;code&gt;~/.ssh&lt;/code&gt; and &lt;code&gt;~/.aws&lt;/code&gt; are blocked.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As a result, the agent can operate normally within the user's workspace without gaining access to all files in the container.&lt;/p&gt;
&lt;p&gt;If the production environment is configured to use bubblewrap but the sandbox cannot actually be created, Shell and MCP use a &lt;strong&gt;fail-closed&lt;/strong&gt; policy: execution is rejected rather than falling back to an unisolated bare process. The REPL follows the same rule when executing model-generated Python code. If the sandbox is unavailable, execution is denied.&lt;/p&gt;
&lt;h3&gt;How subprocess lifecycles and sandbox boundaries are managed&lt;/h3&gt;
&lt;p&gt;Each tool invocation that creates a subprocess uses an independent sandbox and process group with &lt;code&gt;--die-with-parent&lt;/code&gt; enabled. When a user executes &lt;code&gt;/stop&lt;/code&gt;, a task times out, or a new task within the same Scope replaces the current one, the system progressively cancels the current task and uses &lt;code&gt;killpg&lt;/code&gt; to clean up the entire process group. This prevents Shell processes, MCP servers, or their child processes from continuing to run in the background.&lt;br&gt;
Although stdio MCP servers are launched by the SDK itself, their execution commands are also prefixed with bubblewrap so that they use the same file system view as Shell commands. The REPL must likewise enter the sandbox when executing model-generated Python code, preventing execution methods other than Shell from becoming a path around the security boundary.&lt;br&gt;
There are also several implementation details to consider:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;After &lt;code&gt;/app&lt;/code&gt; is overlaid with tmpfs, it must be remounted as read-only to prevent writes to the temporary &lt;code&gt;/app&lt;/code&gt; from silently succeeding.  &lt;/li&gt;
&lt;li&gt;Before entering the sandbox, &lt;code&gt;VIRTUAL_ENV&lt;/code&gt; and &lt;code&gt;PATH&lt;/code&gt; entries pointing to protected locations must also be cleaned up to avoid problems with the Python runtime environment.  &lt;/li&gt;
&lt;li&gt;When the service starts, it performs an actual &lt;code&gt;/bin/true&lt;/code&gt; execution inside the sandbox as a self-check rather than merely verifying that the bubblewrap binary exists.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The current solution primarily addresses file system and service source code isolation. Network isolation through &lt;code&gt;--unshare-net&lt;/code&gt; has not yet been implemented. In addition, CPU and memory quotas have not yet been configured beyond execution timeouts.&lt;/p&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;p&gt;Our production practice can be summarized in four points:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Everything about an agent's state can be represented as files.&lt;/strong&gt; Profiles are Markdown files. History is stored in SQLite. Skills are directories. Memory and configuration are stored as files. Application artifacts include Excel spreadsheets, CSV files, charts, and scripts.  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A shared file system provides state persistence and storage-compute separation.&lt;/strong&gt; Agent Pods are responsible only for computation, while agent state and workspaces are stored in JuiceFS. Pods can be rebuilt at any time without causing user data to disappear with the compute instance.  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The same file system connects multiple AI environments.&lt;/strong&gt; Notebook, training, evaluation, and Jarvis Claw can access the same set of files. Data no longer needs to be repeatedly copied between different systems, and operations can rely on standard file-based tools and workflows.  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Opening the workspace requires layered security boundaries.&lt;/strong&gt; JuiceFS and OpenACL manage user-level file system permissions. Application-level path checks restrict the file access scope of tools running in the main process. Bubblewrap controls subprocesses created by Shell commands, MCP servers, and code execution.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Next, we plan to further explore &lt;strong&gt;agent self-evolution&lt;/strong&gt;. Agent telemetry, memories, and evaluation data will continue to accumulate in the file system. Models will continue to improve, and this accumulated data will become part of the foundation for the agent's future evolution.&lt;/p&gt;
&lt;p&gt;If you have any feedback on this article or ideas to share, we invite you to participate in the &lt;a href="https://github.com/juicedata/juicefs/discussions/"&gt;discussions on GitHub&lt;/a&gt; and join &lt;a href="http://go.juicefs.com/discord"&gt;our community on Discord&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;</description><pubDate>Thu, 10 Sep 2026 06:29:00 +0000</pubDate><guid>https://www.juicefs.com/en/blog/user-stories/hello-builds-stateful-ai-workspace-with-juicefs</guid></item><item><title>Scaling PB-Scale Scientific Data Workloads: How the American Museum of Natural History Powers Research Computing with JuiceFS</title><link>https://www.juicefs.com/en/blog/user-stories/amnh-powers-research-computing-with-juicefs</link><description>&lt;div class="w-block-markdown block-markdown"&gt;&lt;p&gt;In cutting-edge scientific fields like astrophysics and genomics, high-throughput reading of massive datasets and zero-tolerance data integrity are the absolute lifebloods of computational analysis.&lt;/p&gt;
&lt;p&gt;Recently, the JuiceFS team sat down for an in-depth conversation with the Scientific Computing team at the &lt;a href="https://www.amnh.org/"&gt;American Museum of Natural History (AMNH)&lt;/a&gt;. They explained how they use &lt;a href="https://juicefs.com/docs/community/introduction/"&gt;JuiceFS Community Edition&lt;/a&gt; to handle large amounts of research data within an &lt;a href="https://www.openstoragenetwork.org/"&gt;Open Storage Network (OSN)&lt;/a&gt; S3-compatible storage system which was funded by a grant from the &lt;a href="https://www.nsf.gov/"&gt;National Science Foundation (NSF)&lt;/a&gt;, creating a highly reliable and consistent storage setup for academic use.&lt;/p&gt;
&lt;h2&gt;The workload: 95% read-heavy traffic&lt;/h2&gt;
&lt;p&gt;The scientific computing environment at AMNH supports extraordinarily intense interdisciplinary research, operating at a massive scale. Currently, AMNH's OSN nodes have the capacity to store around 3 PB of research data, with approximately 30% of that total volume actively accessed via the NFS + JuiceFS layer. The overall storage architecture is precisely tailored to handle these specific academic patterns:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;A 95% Read-Heavy Profile&lt;/strong&gt;: Workloads include the system's massive reference datasets such as genomic sequences and astronomical survey data in read-only format. The calculations are very throughput- and latency-sensitive. Once a dataset is written, it will be read many times and rarely changed.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;The OSN (Open Storage Network) Model&lt;/strong&gt;: AMNH partners with the Open Storage Network. Standard rack servers and an external JBOD are hosted on-site at the museum but managed remotely by OSN administrators. This setup provides AMNH with cost-effective S3-compatible endpoints while allowing them to maintain physical ownership of the hardware and data.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Seamless Multi-Protocol Access&lt;/strong&gt;: AMNH adopted JuiceFS Community Edition as the distributed file system layer, allowing mounting S3 buckets seamlessly and enabling traditional NFS access to this underlying S3-compatible storage for high-performance computing (HPC) clusters.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;
&lt;div class="w-block-ImageWithCaption block-ImageWithCaption"&gt;&lt;dl&gt;
    &lt;dt&gt;image&lt;/dt&gt;
    &lt;dd&gt;NFS + JuiceFS + OSN&lt;/dd&gt;
    &lt;dt&gt;caption&lt;/dt&gt;
    &lt;dd&gt;AMNH&amp;#x27;s NFS + JuiceFS + OSN storage architecture&lt;/dd&gt;
&lt;/dl&gt;&lt;/div&gt;
&lt;div class="w-block-markdown block-markdown"&gt;&lt;h2&gt;Data integrity first, without silent corruption&lt;/h2&gt;
&lt;p&gt;For scientific research, data consistency is crucial. To prove and continuously observe the system's resilience, the AMNH team conducted rounds of tests during the PoC phase and watched JuiceFS logs and metrics closely in production.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"We have recently observed timeout warnings when JuiceFS writes to the OSN object store, but data integrity issues were never reported. We do want to understand why, though."&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;– Scientific Computing Team, AMNH&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That was one of the discussions we had during the meeting. It turns out that JuiceFS configures all object store SDKs with &lt;code&gt;RetryMaxAttempts=1&lt;/code&gt; and implements custom logic for retries. This way, JuiceFS is able to unify the behavior across all object stores it supports. Thus, in this case, the warning is a precaution, and the data integrity is ensured.&lt;/p&gt;
&lt;p&gt;When comparing JuiceFS to other file systems that claim higher raw performance metrics (often achieved by using "unsafe" write-handling or skipping strict metadata commits), AMNH opted for data consistency.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"We use almost all the default configurations for the JuiceFS client with Redis as the metadata engine, and it's been running in production steadily for 4 years now."&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;– Scientific Computing Team, AMNH&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Current &amp;amp; future tuning options&lt;/h2&gt;
&lt;p&gt;The conversation also continued into how AMNH tunes and considers the JuiceFS client configurations to match their scientific computing patterns needed for the future.&lt;/p&gt;
&lt;h3&gt;The write-back configuration&lt;/h3&gt;
&lt;p&gt;Currently, the only non-default configuration AMNH utilizes is  &lt;a href="https://juicefs.com/docs/community/guide/cache#client-write-cache"&gt;&lt;code&gt;--writeback&lt;/code&gt;&lt;/a&gt; , which smooths out the client-side writing throughput. There are always tradeoffs. Write-back sacrifices a bit of data consistency and requires high disk reliability on the mounting machine. However, given AMNH's current workload pattern (mostly reads), both teams agreed that it is acceptable either way, write-back enabled or not.&lt;/p&gt;
&lt;h3&gt;High-performance caching&lt;/h3&gt;
&lt;p&gt;The teams also evaluated the differences between the Linux kernel's native page cache and JuiceFS' cache for client-side metadata. While the kernel page cache is the fastest, the JuiceFS client-side metadata cache offers more flexibility. In a read-heavy setup, this configuration can save many roundtrips to the metadata engine. Currently, the metadata engine is co-located with the JuiceFS client-mounting host, but in the future, this configuration can be a nice add-on for performance.&lt;/p&gt;
&lt;p&gt;On the file side, since the hardware uses HDDs managed by the OSN object store, the JuiceFS client's local data read cache significantly lowers latency after the first read. Increasing the &lt;a href="https://juicefs.com/docs/community/guide/cache#client-read-cache"&gt;&lt;code&gt;--cachesize&lt;/code&gt;&lt;/a&gt; can further improve performance when needed.&lt;/p&gt;
&lt;h3&gt;The potential of using SQLite as the metadata engine&lt;/h3&gt;
&lt;p&gt;In a highly creative approach, the teams discussed utilizing SQLite on local NVMe storage as their JuiceFS metadata engine. The JuiceFS team highlighted that for standalone sandboxes or read-heavy workloads, SQLite is an exceptional, low-maintenance choice, provided the metadata file is backed up for resilience (which is true for Redis as well). Since for AMNH's current scenario, the primary I/O bottleneck usually lies in the backend object storage rather than the database, SQLite's simplicity makes it incredibly attractive for specific workloads.&lt;/p&gt;
&lt;h2&gt;Final thoughts&lt;/h2&gt;
&lt;p&gt;Managing multi-petabyte scale, strong data consistency, and high-throughput research workloads is a difficult balancing act for any infrastructure team. AMNH has built a resilient, low-maintenance storage environment that lets scientists work without creating massive engineering overhead, using an open architecture and JuiceFS Community Edition on top of an OSN backend.&lt;/p&gt;
&lt;p&gt;Reflecting on their four-year journey of running this system stably in production, the AMNH team summarized their experience seamlessly:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"The implementation on our side is straightforward, and we are happy about it overall."&lt;/em&gt;  &lt;/p&gt;
&lt;p&gt;&lt;em&gt;– Scientific Computing Team, AMNH&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;As data demands in scientific computing continue to grow, this blueprint of combining cost-effective object storage with a robust, reliable file system layer provides a highly reproducible success story for academic and research institutions worldwide.&lt;/p&gt;
&lt;p&gt;If you have any questions for this article, feel free to join &lt;a href="https://github.com/juicedata/juicefs/discussions/"&gt;JuiceFS discussions on GitHub&lt;/a&gt; and our &lt;a href="http://go.juicefs.com/discord"&gt;Discord server&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;</description><pubDate>Thu, 03 Sep 2026 05:29:00 +0000</pubDate><guid>https://www.juicefs.com/en/blog/user-stories/amnh-powers-research-computing-with-juicefs</guid></item></channel></rss>