<?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, 29 Oct 2026 05:36:23 +0000</lastBuildDate><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:23 +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><item><title>How Tencent Cloud Built a Unified Storage Platform with JuiceFS and FoundationDB</title><link>https://www.juicefs.com/en/blog/user-stories/foundationdb-unified-storage</link><description>&lt;div class="w-block-markdown block-markdown"&gt;&lt;p&gt;As &lt;a href="https://en.wikipedia.org/wiki/Big_data"&gt;big data&lt;/a&gt; and &lt;a href="https://en.wikipedia.org/wiki/Artificial_intelligence"&gt;AI&lt;/a&gt; workloads continue to grow, more enterprises are transitioning from tightly coupled storage-compute architectures to storage-compute separation architectures. However, in real-world deployments, enterprises often need to manage multiple storage systems simultaneously, including Cloud Object Storage (COS), S3, and HDFS. These backends differ in access protocols, authentication mechanisms, file system semantics, and metadata performance. This creates challenges in unified access, existing data reuse, and cache acceleration.&lt;/p&gt;
&lt;p&gt;To address these challenges, the &lt;a href="https://en.wikipedia.org/wiki/Tencent_Cloud"&gt;Tencent Cloud&lt;/a&gt; (a cloud computing service operated by &lt;a href="https://en.wikipedia.org/wiki/Tencent"&gt;Tencent&lt;/a&gt;, a multinational technology company headquartered in China) team built an enterprise-grade unified storage solution based on &lt;a href="https://juicefs.com/docs/community/introduction/"&gt;JuiceFS&lt;/a&gt;+FoundationDB. &lt;strong&gt;The solution provides full POSIX semantics for newly created file systems while also integrating existing object storage and HDFS data into a unified namespace, enabling centralized access and cache acceleration&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;In this architecture, FoundationDB serves as the metadata engine, supporting metadata management at the tens-of-billions scale with strong transactional consistency. This is also the first time the JuiceFS community has shared a production practice using FoundationDB for metadata management. Local caching and distributed caching are introduced to reduce remote access latency. Going forward, our team plans to further evolve the platform in areas including lakehouse integration, AI training acceleration, intelligent data tiering, and cross-cluster federation.&lt;/p&gt;
&lt;h2&gt;Challenges: storage gets more complex after storage-compute separation&lt;/h2&gt;
&lt;p&gt;During early customer discussions and proof-of-concept (POC) projects, we found that when enterprises migrate from storage-compute integrated architectures to storage-compute separation architectures, their biggest concerns are not the architecture model itself, but two questions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Can existing data and applications be migrated smoothly?&lt;/li&gt;
&lt;li&gt;Can performance remain close to the original integrated architecture after migration?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Enterprises often operate multiple storage systems simultaneously&lt;/strong&gt;, including COS, S3, and HDFS. These backends differ in access protocols, SDKs, authentication methods, and file system semantics. If Spark, Hive, Flink, or AI training frameworks need to integrate with each storage system separately, development and maintenance costs can quickly increase.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Performance is another major challenge in adopting storage-compute separation&lt;/strong&gt;. When data access paths become longer, remote storage and network communication introduce additional overhead. Meanwhile, running multiple storage systems independently makes it difficult to share and reuse caching capabilities.&lt;/p&gt;
&lt;p&gt;Therefore, a unified storage solution must not only solve multi-backend integration challenges, but also provide reusable cache acceleration capabilities.&lt;/p&gt;
&lt;p&gt;In addition, although &lt;a href="https://en.wikipedia.org/wiki/Object_storage"&gt;object storage&lt;/a&gt; is well suited for massive-scale data storage, it’s generally less efficient than traditional file systems for metadata-intensive operations such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;List&lt;/li&gt;
&lt;li&gt;Stat&lt;/li&gt;
&lt;li&gt;Directory traversal&lt;/li&gt;
&lt;li&gt;Small-file access&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Different storage backends also provide inconsistent support for file system semantics such as directories, permissions, quotas, and snapshots. These differences further complicate unified access for big data and AI workloads.&lt;/p&gt;
&lt;p&gt;Based on these requirements, we chose JuiceFS as the foundation for building an enterprise-grade unified storage platform.&lt;/p&gt;
&lt;h2&gt;Architecture: unified access with two operating modes&lt;/h2&gt;
&lt;p&gt;JuiceFS adopts a metadata-data separation architecture. The &lt;a href="https://juicefs.com/docs/community/databases_for_metadata/"&gt;metadata engine&lt;/a&gt; can be selected based on workload scale and consistency requirements, including Redis, TiKV, and other options.&lt;/p&gt;
&lt;p&gt;For this solution, we selected FoundationDB as the metadata engine, mainly because of its:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Strong transaction model&lt;/li&gt;
&lt;li&gt;Ordered key-value data model&lt;/li&gt;
&lt;li&gt;Automatic data distribution&lt;/li&gt;
&lt;li&gt;Horizontal scalability&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These capabilities enable metadata management at the tens-of-billions scale.&lt;/p&gt;
&lt;p&gt;Based on JuiceFS' core architecture, we built a unified storage platform consisting of:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A unified client layer&lt;/li&gt;
&lt;li&gt;A service-oriented metadata layer&lt;/li&gt;
&lt;li&gt;Multi-level caching&lt;/li&gt;
&lt;li&gt;Multi-backend storage adapters&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;JuiceFS provides fundamental capabilities including:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;File system semantics&lt;/li&gt;
&lt;li&gt;Multi-protocol access&lt;/li&gt;
&lt;li&gt;Object storage-based data paths&lt;/li&gt;
&lt;li&gt;Local caching&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;On top of these capabilities, we further extended the system with the following capabilities to meet the multi-tenant and multi-storage requirements of cloud service scenarios:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Unified authentication&lt;/li&gt;
&lt;li&gt;Multi-volume management&lt;/li&gt;
&lt;li&gt;Unified namespace&lt;/li&gt;
&lt;li&gt;Existing data integration&lt;/li&gt;
&lt;li&gt;Distributed caching&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;On the client side, big data and AI applications can access the system through multiple interfaces:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;HDFS interface&lt;/li&gt;
&lt;li&gt;POSIX mount&lt;/li&gt;
&lt;li&gt;S3 interface&lt;/li&gt;
&lt;li&gt;Python SDK&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The client supports:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Hadoop SDK&lt;/li&gt;
&lt;li&gt;Python SDK&lt;/li&gt;
&lt;li&gt;FUSE mount&lt;/li&gt;
&lt;li&gt;Local cache&lt;/li&gt;
&lt;li&gt;Service discovery&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This allows frameworks such as Spark, Hive, Flink, Presto, and various AI training frameworks to access storage without adapting individually to different backend 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;JuiceFS+FoundationDB&lt;/dd&gt;
    &lt;dt&gt;caption&lt;/dt&gt;
    &lt;dd&gt;Unified storage architecture based on JuiceFS+FoundationDB&lt;/dd&gt;
&lt;/dl&gt;&lt;/div&gt;
&lt;div class="w-block-markdown block-markdown"&gt;&lt;p&gt;For metadata access, we converted JuiceFS' metadata access path into a service-oriented architecture.&lt;/p&gt;
&lt;p&gt;Clients no longer connect directly to FoundationDB. Instead, they communicate with stateless metadata services through RPC. The metadata service centrally provides:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Metadata APIs&lt;/li&gt;
&lt;li&gt;Authentication and authorization&lt;/li&gt;
&lt;li&gt;Multi-volume management&lt;/li&gt;
&lt;li&gt;&lt;a href="https://juicefs.com/docs/community/guide/quota/"&gt;Quota management&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Directory protection&lt;/li&gt;
&lt;li&gt;File protection&lt;/li&gt;
&lt;li&gt;Task management&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ZooKeeper is used for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Service registration&lt;/li&gt;
&lt;li&gt;Service discovery&lt;/li&gt;
&lt;li&gt;Cross-node state synchronization&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The metadata service can scale horizontally as needed, while FoundationDB acts as the backend metadata engine responsible for metadata persistence and transaction processing.&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;Data access architecture&lt;/dd&gt;
    &lt;dt&gt;caption&lt;/dt&gt;
    &lt;dd&gt;Data access architecture for managed mode and external mode&lt;/dd&gt;
&lt;/dl&gt;&lt;/div&gt;
&lt;div class="w-block-markdown block-markdown"&gt;&lt;p&gt;To cover both new file system creation and existing data ingestion scenarios, the underlying storage layer provides two modes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Managed mode&lt;/strong&gt; is designed for newly created file systems. File metadata is written to FoundationDB through the metadata service, and file data is split according to JuiceFS' &lt;a href="https://juicefs.com/docs/community/architecture#how-juicefs-store-files"&gt;chunk/slice/block&lt;/a&gt; model and written to object storage. This provides full POSIX file system semantics.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;External mode&lt;/strong&gt; is designed for existing data reuse. Its core is the Unified File System (UFS) abstraction layer, which abstracts backends such as COS, S3, and HDFS into a unified file system interface, without migrating or taking over the existing metadata and data of those backends. Metadata requests are passed through the metadata service via UFS to the underlying storage, while data reads and writes are performed using the native protocols of the respective backends.&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;UFS multi‑storage adaptation architecture&lt;/dd&gt;
    &lt;dt&gt;caption&lt;/dt&gt;
    &lt;dd&gt;UFS multi‑storage adaptation architecture in external mode&lt;/dd&gt;
&lt;/dl&gt;&lt;/div&gt;
&lt;div class="w-block-markdown block-markdown"&gt;&lt;p&gt;The unified namespace organizes both modes within a single directory structure. To upper‑layer applications, it presents a unified path and access entry. As for the underlying implementation, different directories can correspond either to managed file systems or to mounted existing HDFS or object storage data. This allows new and existing data to coexist under the same access system without requiring large‑scale data migration beforehand.&lt;/p&gt;
&lt;p&gt;On the data access path, the system provides both local caching and &lt;a href="https://juicefs.com/docs/cloud/guide/distributed-cache/"&gt;distributed caching&lt;/a&gt;. Read requests first check the local cache; if missed, they access the distributed cache; if still missed, they fall back to the underlying storage. This reduces remote access latency and backend storage pressure.&lt;/p&gt;
&lt;h2&gt;FoundationDB: design trade‑offs for 10‑billion‑level metadata&lt;/h2&gt;
&lt;p&gt;In the unified storage access layer, the metadata engine determines the system's scalability limit and consistency capabilities. When file counts reach the billion or even 10‑billion level, the metadata system itself becomes the critical bottleneck.&lt;/p&gt;
&lt;h3&gt;Why we chose FoundationDB&lt;/h3&gt;
&lt;p&gt;During the metadata engine selection phase, we focused on several key questions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Whether a single cluster can support 10‑billion‑level metadata&lt;/li&gt;
&lt;li&gt;Whether the transaction model is strong enough&lt;/li&gt;
&lt;li&gt;Whether automatic sharding and horizontal scaling are supported&lt;/li&gt;
&lt;li&gt;Whether operational complexity is manageable&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Traditional relational databases tend to hit bottlenecks in single‑volume scale and horizontal scalability, so we focused our evaluation on distributed key-value solutions, including &lt;a href="https://tikv.org/"&gt;TiKV&lt;/a&gt; and FoundationDB:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;TiKV has been widely adopted in large‑scale metadata scenarios and offers strong horizontal scalability.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;FoundationDB better meets our requirements in terms of strict transaction consistency, ordered key‑value model, automatic data distribution, multi‑replica strong consistency, and operational complexity.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ultimately, we chose FoundationDB as the metadata engine because it’s better suited for the strongly consistent, high‑concurrency, range‑scannable access patterns typical of file system metadata. This practice also allowed our team to accumulate experience in modeling, tuning, and operating FoundationDB in large‑scale metadata scenarios, providing a reference for future use cases such as Hive table metadata management.&lt;/p&gt;
&lt;h3&gt;Key design: multi‑volume isolation and range scans&lt;/h3&gt;
&lt;p&gt;File system metadata naturally has two types of access patterns:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A single cluster must host multiple file systems, requiring clear boundaries between volumes.&lt;/li&gt;
&lt;li&gt;Operations such as directory traversal, attribute queries, and chunk index queries often rely on prefix scans.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Therefore, &lt;strong&gt;key design must both satisfy multi‑volume isolation and closely align with file system access paths, avoiding hot spots or large‑transaction issues at scale&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Leveraging FoundationDB's ordered key-values, we used JuiceFS metadata design method:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Using &lt;code&gt;fsname&lt;/code&gt; as the key prefix to distinguish different file systems&lt;/li&gt;
&lt;li&gt;Organizing attributes, directory entries, chunk indexes, and other metadata related to the same file within a close key space to improve access locality&lt;/li&gt;
&lt;li&gt;Encoding numeric fields in big‑endian order so that lexicographic order aligns with numeric order for sequential scans.&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;FoundationDB metadata key&lt;/dd&gt;
    &lt;dt&gt;caption&lt;/dt&gt;
    &lt;dd&gt;FoundationDB metadata key encoding design&lt;/dd&gt;
&lt;/dl&gt;&lt;/div&gt;
&lt;div class="w-block-markdown block-markdown"&gt;&lt;p&gt;On this basis, multiple file systems can share the same FoundationDB cluster while maintaining independent key spaces. For operations such as list that may scan large amounts of data, pagination is used to control single‑transaction size. In transaction conflict scenarios, optimistic locking and automatic retries are used to reduce lock contention.&lt;/p&gt;
&lt;h3&gt;How to avoid FoundationDB's hard limits&lt;/h3&gt;
&lt;p&gt;FoundationDB has explicit hard limits on key size, value size, and transaction size:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A single key is limited to 10 KB.&lt;/li&gt;
&lt;li&gt;A single value to 100 KB.&lt;/li&gt;
&lt;li&gt;A single transaction to 10 MB total size.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These limits cannot be adjusted via configuration parameters. &lt;strong&gt;When using FoundationDB as a file system metadata engine, we need to pay special attention to operations that tend to enlarge metadata size&lt;/strong&gt;, such as frequent random writes, repeated truncates, fallocate punch hole, and &lt;code&gt;copyFileRange&lt;/code&gt;, which may cause individual values to grow continuously. Large‑scale file copies, large file truncation, batch metadata import, or deleting an entire file system may trigger oversized transactions.&lt;/p&gt;
&lt;p&gt;The highest risk comes from chunk slice accumulation. In JuiceFS' data model, the slice list corresponding to a chunk is stored in a single value, and each slice occupies about 24 bytes. When a chunk accumulates about 4,266 slices, it may hit FoundationDB's 100 KB value limit. Operations such as frequent random writes to the same chunk, repeated truncates, fallocate punch hole, and &lt;code&gt;copyFileRange&lt;/code&gt; will continuously increase the slice count. Without a governance mechanism, a single value can keep growing, eventually causing transaction commit failures.&lt;/p&gt;
&lt;p&gt;This issue also has a subtle implementation aspect: some paths use atomic append operations like &lt;code&gt;AppendIfFits&lt;/code&gt;. This is a blind‑write operation; the transaction cannot know the total value size after the append in advance. If the append exceeds 100 KB, failure may not occur until the transaction commit phase. This means the problem is not exposed early during writes but instead accumulates silently until a commit fails. Therefore, relying solely on retries after failure is insufficient; safety boundaries must be set in the data model and write path.&lt;/p&gt;
&lt;p&gt;To address chunk slice accumulation, we implemented and strengthened the compaction mechanism. &lt;strong&gt;The core idea is to detect chunks with too many slices during read/write operations and merge multiple small slices into fewer large slices to control individual value growth&lt;/strong&gt;. For lightly fragmented chunks, asynchronous compaction can be triggered to avoid blocking writes. When the slice count reaches a safety threshold, synchronous compaction is triggered to prevent it from growing to the 100 KB limit. In practice, &lt;code&gt;maxSlices&lt;/code&gt; is set to 2,500, corresponding to about 60 KB, leaving about 40 KB of headroom below the 100 KB limit.&lt;/p&gt;
&lt;p&gt;During compaction implementation, concurrency and reclamation issues also need to be handled. The merge process uses CAS semantics to ensure the chunk has not been modified concurrently, avoiding data loss. If compaction fails, normal writes are not affected, and it can be retried later. Obsolete slices generated after compaction are passed to the Garbage Collection (GC) process, where reference counting determines whether they are still in use. A delayed‑deletion mechanism supports accidental deletion recovery and background reclamation.&lt;/p&gt;
&lt;p&gt;In addition to chunk slice accumulation, we also examined other risk items such as file system configurations, Kerberos tokens, POSIX locks, extended attributes, and UFS path‑type keys. Overall, these risks are manageable: most values are small, and key design is constrained by file name or path length. The real area requiring governance is still the single‑value expansion caused by chunk slice accumulation.&lt;/p&gt;
&lt;h2&gt;Cache acceleration system: two‑level caching to reduce remote access overhead&lt;/h2&gt;
&lt;p&gt;After storage‑compute separation, data access paths shift from local disks to remote object storage or HDFS. For read‑intensive workloads such as big data analytics and AI training, if every read goes directly back to the underlying storage, network latency and backend access pressure are amplified. Therefore, &lt;strong&gt;the unified storage layer must not only address "how to access multiple storage types" but also "how to make remote data reads faster."&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Our approach is to introduce two‑level caching: client local cache as L1, and distributed cache as L2. Read requests first check the local cache; if hit, return directly. If missed, they access the distributed cache. If still missed, they fall back to the underlying storage and fill the data into the cache system. This provides both the lowest latency from local SSD or memory and the ability to reuse hot data across multiple clients through an independent SSD cache cluster.&lt;/p&gt;
&lt;p&gt;Local caching mainly uses JuiceFS Community Edition's existing capabilities, extended to support external mode. It runs inside the client process, caches data at block granularity by default, and supports least recently used (LRU)  eviction, sequential read prefetching, and OS cache control. The distributed cache is our self‑developed independent cache cluster. Clients use consistent hashing to route the same data block to the same cache node, making it suitable for multi‑node shared reads, scenarios with limited client local storage, or workloads requiring cross‑task hot data reuse.&lt;/p&gt;
&lt;p&gt;The most critical area in the cache system is consistency. In managed mode, every write generates a new slice ID. This causes the cache key to change, so old caches are naturally not hit. Meanwhile, objects in object storage are never modified in place after being written, so no additional invalidation mechanism is needed.&lt;/p&gt;
&lt;p&gt;External mode is more complex, because files in the underlying HDFS or object storage may be directly overwritten by external systems. If the cache key contains only the path, stale data may be read. To address this, &lt;strong&gt;we introduced a fingerprint mechanism in external mode, incorporating file path, block offset, and file fingerprint into the cache key&lt;/strong&gt;. The fingerprint is composed of file modification time and size, and is frozen at open time. When the file is modified externally, the fingerprint changes, so old caches are naturally not hit, satisfying close‑to‑open consistency.&lt;/p&gt;
&lt;p&gt;This brings a trade‑off: managed mode provides finer‑grained cache isolation based on slice IDs, while external mode relies on file fingerprints, which are more coarse‑grained and may invalidate larger cache ranges. However, for scenarios where existing data may be modified by external systems, this is a necessary trade‑off for consistency, and it’s also an area for future optimization.&lt;/p&gt;
&lt;p&gt;In addition to basic read caching, the system supports cache warm-up, cache‑stampede protection, TTL‑based eviction, and transparent degradation. For example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;warmup&lt;/code&gt; command can pre‑load hot data.&lt;/li&gt;
&lt;li&gt;Distributed caching supports batch-warming by directory prefix.&lt;/li&gt;
&lt;li&gt;When the cache layer becomes unavailable, the system can automatically degrade to direct underlying storage access to prevent cache failures from affecting application reads.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Multi‑tenancy and elastic scaling&lt;/h2&gt;
&lt;p&gt;In cloud provider scenarios, the unified storage layer must serve multiple business units, tenants, and file systems simultaneously. Therefore, we designed the metadata service as a stateless architecture. Clients perform service discovery and load balancing through ZooKeeper, and metadata service nodes can scale horizontally on demand to increase overall access capacity and availability.&lt;/p&gt;
&lt;p&gt;Multi‑volume isolation relies on FoundationDB's key prefix design. Each file system uses an independent &lt;code&gt;fsname&lt;/code&gt; prefix, and different volumes have independent key spaces, allowing a single FoundationDB cluster to host multiple file systems. New file systems can be added online without restarting the metadata service.&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;Stateless metadata&lt;/dd&gt;
    &lt;dt&gt;caption&lt;/dt&gt;
    &lt;dd&gt;Stateless metadata service and FoundationDB multi‑volume isolation architecture&lt;/dd&gt;
&lt;/dl&gt;&lt;/div&gt;
&lt;div class="w-block-markdown block-markdown"&gt;&lt;p&gt;In multi‑node deployments, runtime information such as quotas, permissions, directory protection, and task states must also be synchronized across nodes. We use ZooKeeper for cross‑node change notifications, combined with debounce merging, precise key‑level refresh, and periodic polling for fallback, ensuring configuration changes are promptly synchronized to all metadata service nodes.&lt;/p&gt;
&lt;p&gt;Through stateless metadata services, &lt;code&gt;fsname&lt;/code&gt;‑based isolation, and ZooKeeper state synchronization, the system can achieve both multi‑tenant isolation and horizontal scalability at both the service and metadata layers.&lt;/p&gt;
&lt;h2&gt;10‑billion‑level metadata validation&lt;/h2&gt;
&lt;p&gt;We conducted 10‑billion‑level metadata tests based on JuiceFS 1.3.0 and FoundationDB 7.3. The test environment comprised 6 x86 servers running Kylin V10 SP3, with FoundationDB deployed using triple replication and the SSD storage engine.&lt;/p&gt;
&lt;p&gt;The tests were performed after 10.8 billion metadata entries had already been written. Results showed that at the 10‑billion scale, FoundationDB single‑operation latency remained largely consistent with baseline data. Some operations, such as &lt;code&gt;readdir_1k&lt;/code&gt; and lookup, even performed better. Overall, after reaching 10.8 billion inodes in a single volume, metadata operation latency remained in the sub‑millisecond to 2 ms range, indicating no significant performance degradation at scale.&lt;/p&gt;
&lt;p&gt;The table below shows benchmark single‑operation latency (μs/op, lower is better):&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style="text-align: left;"&gt;Operation&lt;/th&gt;
&lt;th style="text-align: left;"&gt;Redis-always&lt;/th&gt;
&lt;th style="text-align: left;"&gt;FoundationDB (official)&lt;/th&gt;
&lt;th style="text-align: left;"&gt;Current environment (10B+)&lt;/th&gt;
&lt;th style="text-align: left;"&gt;vs. Redis&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;mkdir&lt;/td&gt;
&lt;td style="text-align: left;"&gt;558&lt;/td&gt;
&lt;td style="text-align: left;"&gt;1,842&lt;/td&gt;
&lt;td style="text-align: left;"&gt;1,763&lt;/td&gt;
&lt;td style="text-align: left;"&gt;3.2x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;create&lt;/td&gt;
&lt;td style="text-align: left;"&gt;570&lt;/td&gt;
&lt;td style="text-align: left;"&gt;1,761&lt;/td&gt;
&lt;td style="text-align: left;"&gt;1,720&lt;/td&gt;
&lt;td style="text-align: left;"&gt;3.0x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;rename&lt;/td&gt;
&lt;td style="text-align: left;"&gt;728&lt;/td&gt;
&lt;td style="text-align: left;"&gt;1,911&lt;/td&gt;
&lt;td style="text-align: left;"&gt;1,849&lt;/td&gt;
&lt;td style="text-align: left;"&gt;2.5x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;unlink&lt;/td&gt;
&lt;td style="text-align: left;"&gt;658&lt;/td&gt;
&lt;td style="text-align: left;"&gt;1,940&lt;/td&gt;
&lt;td style="text-align: left;"&gt;1,887&lt;/td&gt;
&lt;td style="text-align: left;"&gt;2.9x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;lookup&lt;/td&gt;
&lt;td style="text-align: left;"&gt;173&lt;/td&gt;
&lt;td style="text-align: left;"&gt;1,029&lt;/td&gt;
&lt;td style="text-align: left;"&gt;817&lt;/td&gt;
&lt;td style="text-align: left;"&gt;4.7x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;getattr&lt;/td&gt;
&lt;td style="text-align: left;"&gt;87&lt;/td&gt;
&lt;td style="text-align: left;"&gt;504&lt;/td&gt;
&lt;td style="text-align: left;"&gt;414&lt;/td&gt;
&lt;td style="text-align: left;"&gt;4.8x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;write&lt;/td&gt;
&lt;td style="text-align: left;"&gt;553&lt;/td&gt;
&lt;td style="text-align: left;"&gt;1,747&lt;/td&gt;
&lt;td style="text-align: left;"&gt;1,710&lt;/td&gt;
&lt;td style="text-align: left;"&gt;3.1x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;readdir_10&lt;/td&gt;
&lt;td style="text-align: left;"&gt;280&lt;/td&gt;
&lt;td style="text-align: left;"&gt;1,744&lt;/td&gt;
&lt;td style="text-align: left;"&gt;1,357&lt;/td&gt;
&lt;td style="text-align: left;"&gt;4.8x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;readdir_1k&lt;/td&gt;
&lt;td style="text-align: left;"&gt;1,490&lt;/td&gt;
&lt;td style="text-align: left;"&gt;15,276&lt;/td&gt;
&lt;td style="text-align: left;"&gt;1,185&lt;/td&gt;
&lt;td style="text-align: left;"&gt;0.8x&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;In extreme write tests, we used 15 concurrent processes to perform &lt;code&gt;juicefs clone&lt;/code&gt; for metadata cloning, validating FoundationDB's write ceiling. Results showed that under the 6‑node + SSD configuration, stable‑phase write throughput was approximately &lt;strong&gt;11,000–15,000 inodes/s&lt;/strong&gt;. Bottleneck analysis indicated that the main pressure was on storage write queues and disk I/O, rather than CPU or network. Future improvements can be made by adding storage processes, upgrading disk performance, or scaling Commit Proxy and TLog components.&lt;/p&gt;
&lt;p&gt;Inode creation:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style="text-align: left;"&gt;Phase&lt;/th&gt;
&lt;th style="text-align: left;"&gt;Inode creation rate&lt;/th&gt;
&lt;th style="text-align: left;"&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;Initial peak&lt;/td&gt;
&lt;td style="text-align: left;"&gt;23,000+ inodes/s&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Peak performance when the write queue is not yet full&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;Stable phase (after 5–6 minutes)&lt;/td&gt;
&lt;td style="text-align: left;"&gt;15,000 inodes/s&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Write queue gradually fills up&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;After queue full (after 10+ minutes)&lt;/td&gt;
&lt;td style="text-align: left;"&gt;11,000–13,000 inodes/s&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Disk I/O becomes the bottleneck; FDB throttling protection is triggered&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;For high availability, we validated scenarios with 1‑node and 2‑node failures. With 1‑node failure, the service remained available, and FoundationDB automatically triggered replica repair and data migration. With 2‑node failure, the service remained available, but the cluster's fault tolerance dropped to zero—it could no longer tolerate additional failures. After recovery, the system triggered data rebalancing, with a complete recovery time of approximately 4 hours in testing. This process introduces additional I/O pressure, so production environments must pay close attention to disk watermarks, single‑disk failures, and resource consumption during recovery.&lt;/p&gt;
&lt;p&gt;For capacity planning, test data showed that at 5 billion inodes, FoundationDB disk usage was approximately 6.1 TB; at 10.8 billion inodes, it was approximately 10.1 TB. After accounting for triple replication, compression, and reserved space, approximately &lt;strong&gt;120 GB per 1 billion inodes&lt;/strong&gt; can be used as a baseline capacity estimate.&lt;/p&gt;
&lt;p&gt;Through this validation, we’ve essentially confirmed that FoundationDB can support 10‑billion‑level metadata per volume while maintaining stable metadata access performance at that scale. At the same time, the triple‑replica architecture provides good failure recovery capabilities, though production environments still require careful capacity planning, disk monitoring, and I/O management during recovery.&lt;/p&gt;
&lt;h2&gt;Summary and future plans&lt;/h2&gt;
&lt;p&gt;At present, this unified storage access layer built on JuiceFS+FoundationDB has completed core capability construction in big data storage‑compute separation scenarios, including unified client access, leveraging of external data, multi‑level cache acceleration, 10‑billion‑level metadata management, and multi‑tenant scalability. Moving forward, we’ll continue to evolve around lakehouse integration, AI training, and storage governance.&lt;/p&gt;
&lt;p&gt;In the lakehouse direction, we plan to strengthen integration with table formats such as Iceberg and Hudi through the unified storage layer, enabling upper‑layer data lake and data warehouse scenarios to reuse unified storage access, permission management, and cache acceleration capabilities.&lt;/p&gt;
&lt;p&gt;For AI training, we’ll further optimize cache warm-up and near‑local caching to reduce remote read amplification and GPU wait times in training jobs. We’ll also explore model checkpoint management using snapshot capabilities, making intermediate state saving, recovery, and reuse more efficient during training.&lt;/p&gt;
&lt;p&gt;In storage governance, we’ll explore intelligent tiering capabilities, automatically migrating data between SSD, HDD, and object storage based on access frequency, achieving a better balance between performance and cost. For larger‑scale cloud deployments, we’ll continue to advance cross‑cluster federation capabilities, enabling metadata synchronization, routing, and unified access across multiple clusters.&lt;/p&gt;
&lt;p&gt;Going forward, we’ll continue to iterate around performance, cost, elasticity, and data governance, enabling more workloads to access and manage underlying data in a unified manner.&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, 27 Aug 2026 08:39:00 +0000</pubDate><guid>https://www.juicefs.com/en/blog/user-stories/foundationdb-unified-storage</guid></item></channel></rss>