1"use strict";(globalThis.webpackChunkwebsite=globalThis.webpackChunkwebsite||[]).push([[2147],{50748(e,n,s){s.r(n),s.d(n,{assets:()=>c,contentTitle:()=>o,default:()=>h,frontMatter:()=>a,metadata:()=>r,toc:()=>d});const r=JSON.parse('{"id":"application-chain/guide-appchain-storage","title":"Storage","description":"Configure AppChain storage \u2014 in-memory for development, RocksDB for production, storage interfaces for custom implementations","source":"@site/docs/application-chain/guide-appchain-storage.md","sourceDirName":"application-chain","slug":"/application-chain/guide-appchain-storage","permalink":"/docs/application-chain/guide-appchain-storage","draft":false,"unlisted":false,"editUrl":"https://github.com/Nethereum/Nethereum.Documentation/tree/main/docs/application-chain/guide-appchain-storage.md","tags":[],"version":"current","sidebarPosition":3,"frontMatter":{"title":"Storage","sidebar_label":"Storage","sidebar_position":3,"description":"Configure AppChain storage \u2014 in-memory for development, RocksDB for production, storage interfaces for custom implementations"},"sidebar":"docsSidebar","previous":{"title":"AppChain Quickstart","permalink":"/docs/application-chain/guide-appchain-quickstart"},"next":{"title":"Syncing","permalink":"/docs/application-chain/guide-appchain-sync"}}');var t=s(74848),i=s(28453);const a={title:"Storage",sidebar_label:"Storage",sidebar_position:3,description:"Configure AppChain storage \u2014 in-memory for development, RocksDB for production, storage interfaces for custom implementations"},o="Storage",c={},d=[{value:"Prerequisites",id:"prerequisites",level:2},{value:"Storage Interfaces",id:"storage-interfaces",level:2},{value:"In-Memory Storage",id:"in-memory-storage",level:2},{value:"RocksDB Storage",id:"rocksdb-storage",level:2},{value:"Dependency Injection",id:"dependency-injection",level:3},{value:"Column Families",id:"column-families",level:2},{value:"Performance Tuning",id:"performance-tuning",level:2},{value:"State Snapshots",id:"state-snapshots",level:2},{value:"Choosing a Backend",id:"choosing-a-backend",level:2},{value:"Common Gotchas",id:"common-gotchas",level:2},{value:"Next Steps",id:"next-steps",level:2}];function l(e){const n={a:"a",admonition:"admonition",blockquote:"blockquote",code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",li:"li",p:"p",pre:"pre",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,i.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.header,{children:(0,t.jsx)(n.h1,{id:"storage",children:"Storage"})}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"PREVIEW"})," \u2014 AppChain packages are in preview. APIs may change between releases."]}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"Every AppChain stores blocks, transactions, receipts, logs, account state, and trie nodes. The storage layer is fully pluggable through CoreChain interfaces \u2014 swap between in-memory (fast, ephemeral) and RocksDB (persistent, production-ready) without changing any application code. This guide covers both built-in backends and how the storage interfaces work."}),"\n",(0,t.jsxs)(n.admonition,{title:"The Simple Way",type:"tip",children:[(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"# RocksDB persistent storage (default)\nnethereum-appchain --db-path ./chaindata\n\n# In-memory (development, no persistence)\nnethereum-appchain --in-memory\n"})}),(0,t.jsx)(n.p,{children:"The CLI handles storage setup automatically. This guide is for when you need programmatic control or want to tune RocksDB performance."})]}),"\n",(0,t.jsx)(n.h2,{id:"prerequisites",children:"Prerequisites"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"dotnet add package Nethereum.CoreChain # Storage interfaces + in-memory\ndotnet add package Nethereum.CoreChain.RocksDB # RocksDB backend\n"})}),"\n",(0,t.jsx)(n.h2,{id:"storage-interfaces",children:"Storage Interfaces"}),"\n",(0,t.jsx)(n.p,{children:"CoreChain defines six storage interfaces that every chain implementation uses. Whether you're running a DevChain, AppChain, or building something custom, these are the data access contracts:"}),"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"Interface"}),(0,t.jsx)(n.th,{children:"What It Stores"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"IBlockStore"})}),(0,t.jsx)(n.td,{children:"Block headers by hash and number"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"ITransactionStore"})}),(0,t.jsx)(n.td,{children:"Signed transactions with block location"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"IReceiptStore"})}),(0,t.jsx)(n.td,{children:"Transaction receipts with gas and status"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"ILogStore"})}),(0,t.jsx)(n.td,{children:"Event logs with bloom filter indexing"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"IStateStore"})}),(0,t.jsx)(n.td,{children:"Account state, contract storage, bytecode, snapshots"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"ITrieNodeStore"})}),(0,t.jsx)(n.td,{children:"Patricia Merkle Trie nodes for state root computation"})]})]})]}),"\n",(0,t.jsxs)(n.p,{children:["Every storage operation is async \u2014 both in-memory and RocksDB implementations use ",(0,t.jsx)(n.code,{children:"Task"}),"-based APIs so the calling code doesn't need to know which backend is active."]}),"\n",(0,t.jsx)(n.h2,{id:"in-memory-storage",children:"In-Memory Storage"}),"\n",(0,t.jsxs)(n.p,{children:["The in-memory backend stores everything in ",(0,t.jsx)(n.code,{children:"ConcurrentDictionary"})," structures. Data is lost when the process exits \u2014 ideal for tests, demos, and short-lived chains:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-csharp",children:"using Nethereum.CoreChain.Storage.InMemory;\n\nvar blockStore = new InMemoryBlockStore();\nvar txStore = new InMemoryTransactionStore(blockStore);\nvar receiptStore = new InMemoryReceiptStore();\nvar logStore = new InMemoryLogStore();
1\nvar stateStore = new InMemoryStateStore();\nvar trieNodeStore = new InMemoryTrieNodeStore();\n"})}),"\n",(0,t.jsxs)(n.p,{children:["Note that ",(0,t.jsx)(n.code,{children:"InMemoryTransactionStore"})," takes a reference to ",(0,t.jsx)(n.code,{children:"blockStore"})," \u2014 it needs to look up block hashes when querying transactions by block number."]}),"\n",(0,t.jsx)(n.p,{children:"Wire these into an AppChain:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-csharp",children:'using Nethereum.AppChain;\n\nvar config = AppChainConfig.CreateWithName("TestChain", chainId: 420420);\nconfig.SequencerAddress = sequencerAddress;\n\nvar appChain = new AppChain(config,\n blockStore, txStore, receiptStore,\n logStore, stateStore, trieNodeStore);\n\nawait appChain.InitializeAsync();\n'})}),"\n",(0,t.jsx)(n.p,{children:"Or use the builder, which defaults to in-memory:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-csharp",children:'var chain = await new AppChainBuilder("TestChain", 420420)\n .WithOperator(privateKey)\n .BuildAsync(); // In-memory by default\n'})}),"\n",(0,t.jsx)(n.h2,{id:"rocksdb-storage",children:"RocksDB Storage"}),"\n",(0,t.jsxs)(n.p,{children:["For production AppChains that need data to survive restarts, use RocksDB. The ",(0,t.jsx)(n.code,{children:"RocksDbManager"})," coordinates a single RocksDB instance with multiple column families optimized for blockchain workloads:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-csharp",children:'using Nethereum.CoreChain.RocksDB;\nusing Nethereum.CoreChain.RocksDB.Stores;\n\nvar options = new RocksDbStorageOptions\n{\n DatabasePath = "./chaindata"\n};\n\nusing var manager = new RocksDbManager(options);\n\nvar blockStore = new RocksDbBlockStore(manager);\nvar txStore = new RocksDbTransactionStore(manager, blockStore);\nvar receiptStore = new RocksDbReceiptStore(manager, blockStore);\nvar logStore = new RocksDbLogStore(manager);\nvar stateStore = new RocksDbStateStore(manager);\nvar trieNodeStore = new RocksDbTrieNodeStore(manager);\n'})}),"\n",(0,t.jsxs)(n.p,{children:["All RocksDB stores share a single database instance through the manager. This is important \u2014 you must use one ",(0,t.jsx)(n.code,{children:"RocksDbManager"})," per database path, and all stores must come from the same manager."]}),"\n",(0,t.jsx)(n.p,{children:"Wire into an AppChain the same way as in-memory:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-csharp",children:"var appChain = new AppChain(config,\n blockStore, txStore, receiptStore,\n logStore, stateStore, trieNodeStore);\n"})}),"\n",(0,t.jsx)(n.p,{children:"Or via the builder:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-csharp",children:'var chain = await new AppChainBuilder("MyChain", 420420)\n .WithOperator(privateKey)\n .WithStorage(StorageType.RocksDb, "./chaindata")\n .BuildAsync();\n'})}),"\n",(0,t.jsx)(n.h3,{id:"dependency-injection",children:"Dependency Injection"}),"\n",(0,t.jsx)(n.p,{children:"For ASP.NET Core or hosted service scenarios, register RocksDB storage via DI:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-csharp",children:'services.AddRocksDbStorage("./chaindata");\n\n// Or with full options\nservices.AddRocksDbStorage(new RocksDbStorageOptions\n{\n DatabasePath = "./chaindata",\n BlockCacheSize = 256 * 1024 * 1024, // 256MB read cache\n EnableStatistics = true\n});\n'})}),"\n",(0,t.jsxs)(n.p,{children:["This registers all store implementations as singletons, resolving ",(0,t.jsx)(n.code,{children:"IBlockStore"}),", ",(0,t.jsx)(n.code,{children:"IStateStore"}),", etc. from the container."]}),"\n",(0,t.jsx)(n.h2,{id:"column-families",children:"Column Families"}),"\n",(0,t.jsx)(n.p,{children:"RocksDB organizes data into column families \u2014 each with its own write buffer, bloom filter, and compaction settings. This is why RocksDB outperforms a naive key-value store for blockchain data: block lookups, state queries, and log filters each get optimized independently."}),"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"Column Family"}),(0,t.jsx)(n.th,{children:"Data"}),(0,t.jsx)(n.th,{children:"Access Pattern"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"blocks"})}),(0,t.jsx)(n.td,{children:"Block headers"}),(0,t.jsx)(n.td,{children:"Sequential writes, random reads by hash"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"block_numbers"})}),(0,t.jsx)(n.td,{children:"Number \u2192 hash index"}),(0,t.jsx)(n.td,{children:"Sequential writes, point lookups"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"transactions"})}),(0,t.jsx)(n.td,{children:"Signed transactions"}),(0,t.jsx)(n.td,{children:"Batch writes per block, random reads by hash"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"tx_by_block"})}),(0,t.jsx)(n.td,{children:"Block \u2192 transaction index"}),(0,t.jsx)(n.td,{children:"Batch writes, range scans"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"receipts"})}),(0,t.jsx)(n.td,{children:"Transaction receipts"}),(0,t.jsx)(n.td,{children:"Batch writes per block, random reads"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"logs"})}),(0,t.jsx)(n.td,{children:"Event logs"}),(0,t.jsx)(n.td,{children:"Batch writes, filter scans"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"log_by_address"})}),(0,t.jsx)(n.td,{children:"Address \u2192 log index"}),(0,t.jsx)(n.td,{children:"Append-only, filter scans"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"state_accounts"})}),(0,t.jsx)(n.td,{children:"Account state (balance, nonce, code hash)"}),(0,t.jsx)(n.td,{children:"Heavy read/write, point lookups"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"state_storage"})}),(0,t.jsx)(n.td,{children:"Contract storage slots"}),(0,t.jsx)(n.td,{children:"Heavy read/write, point lookups"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"state_code"})}),(0,t.jsx)(n.td,{children:"Contract bytecode"}),(0,t.jsx)(n.td,{children:"Write-once, random reads"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"trie_nodes"})}),(0,t.jsx)(n.td,{children:"Patricia trie nodes"}),(0,t.jsx)(n.td,{children:"Heavy read/write during block production"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"metadata"})}),(0,t.jsx)(n.td,{children:"Chain metadata (height, genesis hash)"}),(0,t.jsx)(n.td,{children:"Rare reads/writes"})]})]})]}),"\n",(0,t.jsx)(n.h2,{id:"performance-tuning",children:"Performance Tuning"}),"\n",(0,t.jsxs)(n.p,{children:["The default ",(0,t.jsx)(n.code,{children:"RocksDbStorageOptions"})," work well for most AppChains. For high-throughput scenarios, tune these parameters:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-csharp",children:'var options = new RocksDbStorageOptions\n{\n DatabasePath = "./chaindata",\n\n // Read cache \u2014 increase for read-heavy workloads (default: 128MB)\n BlockCacheSize = 256 * 1024 * 1024,\n\n // Write buffer \u2014 increase for write-heavy workloads (default: 64MB)\n WriteBufferSize = 128 * 1024 * 1024,\n\n // Number of write buffers before flush (default: 3)\n MaxWr
1iteBufferNumber = 4,\n\n // Background compaction threads (default: 4)\n MaxBackgroundCompactions = 8,\n\n // Background flush threads (default: 2)\n MaxBackgroundFlushes = 4,\n\n // Bloom filter bits per key \u2014 higher = more memory, faster lookups (default: 10)\n BloomFilterBitsPerKey = 10,\n\n // Enable RocksDB internal statistics (adds overhead)\n EnableStatistics = false\n};\n'})}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Guidelines:"})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Read-heavy"})," (followers serving queries): increase ",(0,t.jsx)(n.code,{children:"BlockCacheSize"})]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Write-heavy"})," (sequencer producing blocks): increase ",(0,t.jsx)(n.code,{children:"WriteBufferSize"})," and ",(0,t.jsx)(n.code,{children:"MaxWriteBufferNumber"})]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Many concurrent readers"}),": increase ",(0,t.jsx)(n.code,{children:"MaxBackgroundCompactions"})," based on CPU cores"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"SSD vs HDD"}),": SSDs benefit from higher parallelism; HDDs need lower compaction threads to avoid thrashing"]}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"state-snapshots",children:"State Snapshots"}),"\n",(0,t.jsx)(n.p,{children:"The state store supports snapshots for EVM execution rollback \u2014 this is how block production works internally. The producer takes a snapshot before executing a block, and reverts if execution fails:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-csharp",children:"var stateStore = new RocksDbStateStore(manager);\n\n// Take snapshot before block execution\nvar snapshotId = await stateStore.TakeSnapshotAsync();\n\ntry\n{\n // Execute transactions (modifies state)\n // ...\n\n // Commit on success \u2014 snapshot is discarded\n}\ncatch\n{\n // Revert on failure \u2014 state returns to snapshot point\n await stateStore.RevertToSnapshotAsync(snapshotId);\n}\n"})}),"\n",(0,t.jsxs)(n.p,{children:["You typically don't call this directly \u2014 the ",(0,t.jsx)(n.code,{children:"BlockProducer"})," and ",(0,t.jsx)(n.code,{children:"TransactionProcessor"})," in CoreChain handle snapshot management automatically."]}),"\n",(0,t.jsx)(n.h2,{id:"choosing-a-backend",children:"Choosing a Backend"}),"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"Criterion"}),(0,t.jsx)(n.th,{children:"In-Memory"}),(0,t.jsx)(n.th,{children:"RocksDB"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.strong,{children:"Persistence"})}),(0,t.jsx)(n.td,{children:"None \u2014 lost on restart"}),(0,t.jsx)(n.td,{children:"Full \u2014 survives restarts"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.strong,{children:"Speed"})}),(0,t.jsx)(n.td,{children:"Fastest (no I/O)"}),(0,t.jsx)(n.td,{children:"Fast (optimized column families)"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.strong,{children:"Memory usage"})}),(0,t.jsx)(n.td,{children:"Grows with chain size"}),(0,t.jsx)(n.td,{children:"Bounded by cache settings"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.strong,{children:"Use case"})}),(0,t.jsx)(n.td,{children:"Tests, demos, short-lived chains"}),(0,t.jsx)(n.td,{children:"Production, long-running chains"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.strong,{children:"CLI flag"})}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"--in-memory"})}),(0,t.jsxs)(n.td,{children:[(0,t.jsx)(n.code,{children:"--db-path ./chaindata"})," (default)"]})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.strong,{children:"Builder method"})}),(0,t.jsx)(n.td,{children:"Default"}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:".WithStorage(StorageType.RocksDb, path)"})})]})]})]}),"\n",(0,t.jsx)(n.p,{children:"For development, start with in-memory and switch to RocksDB when you need persistence. The storage interfaces guarantee your application code doesn't change."}),"\n",(0,t.jsx)(n.h2,{id:"common-gotchas",children:"Common Gotchas"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"One manager per path"})," \u2014 don't create multiple ",(0,t.jsx)(n.code,{children:"RocksDbManager"})," instances pointing at the same directory. RocksDB locks the database file; the second instance will fail."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Dispose the manager"})," \u2014 ",(0,t.jsx)(n.code,{children:"RocksDbManager"})," implements ",(0,t.jsx)(n.code,{children:"IDisposable"}),". Use ",(0,t.jsx)(n.code,{children:"using"})," or dispose it in your shutdown logic. Not disposing can corrupt the database."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"RocksDB native libraries"})," \u2014 the ",(0,t.jsx)(n.code,{children:"Nethereum.CoreChain.RocksDB"})," NuGet package includes native RocksDB binaries. On Linux, you may
1need ",(0,t.jsx)(n.code,{children:"librocksdb"})," installed separately depending on your distribution."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Disk space"})," \u2014 a busy AppChain can grow the database quickly. Monitor disk usage and consider pruning strategies for long-running chains."]}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"next-steps",children:"Next Steps"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:(0,t.jsx)(n.a,{href:"guide-appchain-quickstart",children:"AppChain Quickstart"})})," \u2014 launch a sequencer and follower with the CLI"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:(0,t.jsx)(n.a,{href:"guide-appchain-sync",children:"Syncing Follower Nodes"})})," \u2014 how followers sync and verify chain state using these storage backends"]}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(l,{...e})}):l(e)}},28453(e,n,s){s.d(n,{R:()=>a,x:()=>o});var r=s(96540);const t={},i=r.createContext(t);function a(e){const n=r.useContext(i);return r.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:a(e.components),r.createElement(i.Provider,{value:n},e.children)}}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.