Storage Costs
Understanding storage costs helps you budget effectively and avoid service interruptions. This guide explains how to calculate costs and fund your account for Filecoin storage.
How Storage Costs Work
Section titled “How Storage Costs Work”Storage operates on a pay-per-epoch model where you deposit USDFC tokens and set allowances that control how much the storage service can spend.
Pricing Components
Section titled “Pricing Components”| Component | Cost | Notes |
|---|---|---|
| Storage | $2.50/TiB/month | Minimum $0.06/month per data set (~24.567 GiB threshold) |
| CDN Egress | $14/TiB downloaded | 1 USDFC top-up ≈ 71.5 GiB of downloads |
| CDN Setup | 1 USDFC (one-time) | Per data set; reusing existing data sets incurs no cost |
Pricing Logic:
- Storage < 24.567 GiB: Minimum $0.06/month applies
- Storage ≥ 24.567 GiB: Actual cost
(bytes / TiB) × $2.50/month - CDN data sets require 1 USDFC setup on first creation only
- CDN egress credits can be topped up anytime
Real-World Cost Examples
Section titled “Real-World Cost Examples”Example 1: NFT Collection (10,000 × 5 KiB ≈ 48.82 MiB)
Section titled “Example 1: NFT Collection (10,000 × 5 KiB ≈ 48.82 MiB)”// 48.82 MiB less than 24.567 GiB threshold// Price is $0.06/monthconst const PRICE_PER_MONTH: 0.06
PRICE_PER_MONTH = 0.06;const const months: 24
months = 24;const const PRICE_FOR_24_MONTHS: number
PRICE_FOR_24_MONTHS = const PRICE_PER_MONTH: 0.06
PRICE_PER_MONTH * 24; // 1.44 USDFC| Duration | Total Cost |
|---|---|
| 1 month | 0.06 USDFC |
| 24 months | 1.44 USDFC |
Example 2: User Content Platform with CDN
Section titled “Example 2: User Content Platform with CDN”- Storage: 1,000 users × 100 MiB ≈ 100,000 MiB
- Traffic: 1,000 users × 100 MiB/month ≈ 100,000 MiB/month egress
const const STORAGE_PRICE_PER_TIB_PER_MONTH: 2.5
STORAGE_PRICE_PER_TIB_PER_MONTH = 2.5; // $2.50/TiB/monthconst const CDN_EGRESS_PRICE_PER_TIB: 14
CDN_EGRESS_PRICE_PER_TIB = 14; // $14/TiB downloadedconst const storageMiB: 100000
storageMiB = 100_000;const const egressMiB: 100000
egressMiB = 100_000;
// Storage: 100,000 MiB ≈ 0.0953 TiBconst const storageTiB: number
storageTiB = const storageMiB: 100000
storageMiB / 1024 / 1024;
// Egress: 100,000 MiB ≈ 0.0953 TiBconst const egressTiB: number
egressTiB = const egressMiB: 100000
egressMiB / 1024 / 1024;
// Storage cost per month: 0.0953 TiB × $2.50 ≈ $0.238/monthconst const storageCostPerMonth: number
storageCostPerMonth = const storageTiB: number
storageTiB * const STORAGE_PRICE_PER_TIB_PER_MONTH: 2.5
STORAGE_PRICE_PER_TIB_PER_MONTH;
// Egress cost per month: 0.0953 TiB × $14 ≈ $1.334/monthconst const egressCostPerMonth: number
egressCostPerMonth = const egressTiB: number
egressTiB * const CDN_EGRESS_PRICE_PER_TIB: 14
CDN_EGRESS_PRICE_PER_TIB;
// Total cost per month: $0.238/month + $1.334/month ≈ $1.572/monthconst const totalCostPerMonth: number
totalCostPerMonth = const storageCostPerMonth: number
storageCostPerMonth + const egressCostPerMonth: number
egressCostPerMonth;
// Total cost for 24 months: $1.572/month × 24 ≈ $37.728const const totalCostFor24Months: number
totalCostFor24Months = const totalCostPerMonth: number
totalCostPerMonth * 24;| Cost Component | Per Month | 24 Months |
|---|---|---|
| Storage | ≈ 0.238 USDFC | ≈ 5.71 USDFC |
| CDN Egress | ≈ 1.334 USDFC | ≈ 32.016 USDFC |
| Total | ≈ 1.572 USDFC | ≈ 37.728 USDFC |
Warm Storage Service Approvals
Section titled “Warm Storage Service Approvals”Before uploading, approve the WarmStorage operator and fund your account. FWSS requires a 30-day prepayment buffer—when your balance drops below 30 days, the provider may remove your data.
Approval Components:
| Component | Purpose | Formula When Adding Storage |
|---|---|---|
| Deposit Amount | USDFC tokens for storage duration | Total cost for desired months |
| Rate Allowance | Max spending per epoch (cumulative) | currentRateUsed + newRate |
| Lockup Allowance | 30-day prepayment buffer (cumulative) | currentLockupUsed + (newRate × 86,400) |
| Max Lockup Period | Safety limit on locked funds | constant of 86,400 epochs (30 days) |
Detailed Calculator Guide
Section titled “Detailed Calculator Guide”Learn how to calculate storage costs, required operator allowances and fund your account for future storage needs.
In this guide we will calculate the costs for a 1 GiB storage capacity for 12 months.
Step 1: Calculate Base Storage Costs
Section titled “Step 1: Calculate Base Storage Costs”Get pricing information and calculate the cost per epoch for your storage capacity:
// Get pricing structureconst const warmStorageService: WarmStorageService
warmStorageService = class WarmStorageService
WarmStorageService.WarmStorageService.create(options: { transport?: Transport; chain?: Chain; account: Account;}): WarmStorageService
create({ account: Account
account: function privateKeyToAccount(privateKey: Hex, options?: PrivateKeyToAccountOptions): PrivateKeyAccount
privateKeyToAccount('0x...') })
const { const minimumPricePerMonth: bigint
minimumPricePerMonth, const epochsPerMonth: bigint
epochsPerMonth, const pricePerTiBPerMonthNoCDN: bigint
pricePerTiBPerMonthNoCDN } = await const warmStorageService: WarmStorageService
warmStorageService.WarmStorageService.getServicePrice(): Promise<getServicePrice.OutputType>
getServicePrice()
// Calculate base cost per monthconst const bytesToStore: bigint
bytesToStore = const SIZE_CONSTANTS: { readonly KiB: 1024n; readonly MiB: bigint; readonly GiB: bigint; readonly TiB: bigint; readonly PiB: bigint; readonly MAX_UPLOAD_SIZE: 1065353216; readonly MIN_UPLOAD_SIZE: 127; readonly DEFAULT_UPLOAD_BATCH_SIZE: 32;}
SIZE_CONSTANTS.type GiB: bigint
GiB // 1 GiBlet let pricePerMonth: bigint
pricePerMonth = (const pricePerTiBPerMonthNoCDN: bigint
pricePerTiBPerMonthNoCDN * var BigInt: BigIntConstructor(value: bigint | boolean | number | string) => bigint
BigInt(const bytesToStore: bigint
bytesToStore)) / var BigInt: BigIntConstructor(value: bigint | boolean | number | string) => bigint
BigInt(const SIZE_CONSTANTS: { readonly KiB: 1024n; readonly MiB: bigint; readonly GiB: bigint; readonly TiB: bigint; readonly PiB: bigint; readonly MAX_UPLOAD_SIZE: 1065353216; readonly MIN_UPLOAD_SIZE: 127; readonly DEFAULT_UPLOAD_BATCH_SIZE: 32;}
SIZE_CONSTANTS.type TiB: bigint
TiB)
// Apply minimum pricing if neededif (let pricePerMonth: bigint
pricePerMonth < const minimumPricePerMonth: bigint
minimumPricePerMonth) { let pricePerMonth: bigint
pricePerMonth = const minimumPricePerMonth: bigint
minimumPricePerMonth}
// Calculate per-epoch costconst const pricePerEpoch: bigint
pricePerEpoch = let pricePerMonth: bigint
pricePerMonth / const epochsPerMonth: bigint
epochsPerMonth
var console: Console
console.Console.log(...data: any[]): void
The console.log() static method outputs a message to the console.
log("Monthly cost:", let pricePerMonth: bigint
pricePerMonth)var console: Console
console.Console.log(...data: any[]): void
The console.log() static method outputs a message to the console.
log("Per-epoch cost:", const pricePerEpoch: bigint
pricePerEpoch)Step 2: Calculate Required Allowances
Section titled “Step 2: Calculate Required Allowances”Calculate cumulative allowances for your new storage, accounting for existing usage.
// Define storage duration in months (minimum 1 month)const const persistencePeriodInMonths: 12n
persistencePeriodInMonths = 12n;
// Check if creating a new CDN dataset (creates context to determine if one exists)const const storageContext: StorageContext
storageContext = await const synapse: Synapse
synapse.Synapse.storage: StorageManager
storage.StorageManager.createContext(options?: StorageServiceOptions): Promise<StorageContext>
createContext({ StorageServiceOptions.withCDN?: boolean
withCDN: true, StorageServiceOptions.metadata?: Record<string, string>
metadata: { type Application: string
Application: "MyApp", type Version: string
Version: "1.0.0" },});const const newCDNDataSetNeeded: boolean
newCDNDataSetNeeded = const storageContext: StorageContext
storageContext.StorageContext.dataSetId: bigint | undefined
dataSetId === null;
const const warmStorageDefaultLockupPeriod: 30n
warmStorageDefaultLockupPeriod = const TIME_CONSTANTS: { readonly EPOCH_DURATION: 30; readonly EPOCHS_PER_DAY: 2880n; readonly EPOCHS_PER_MONTH: 86400n; readonly DAYS_PER_MONTH: 30n; readonly DEFAULT_LOCKUP_DAYS: 30n; readonly PERMIT_DEADLINE_DURATION: 3600;}
TIME_CONSTANTS.type DEFAULT_LOCKUP_DAYS: 30n
DEFAULT_LOCKUP_DAYS; // 30 days
// Calculate total cost and lockup needed for THIS storage additionconst const cdnDataSetCreationCost: bigint
cdnDataSetCreationCost = 10n ** 18n; // 1 USDFClet let totalCostNeeded: bigint
totalCostNeeded = const pricePerMonth: bigint
pricePerMonth * const persistencePeriodInMonths: 12n
persistencePeriodInMonths;let let lockupNeeded: bigint
lockupNeeded = const pricePerMonth: bigint
pricePerMonth * const warmStorageDefaultLockupPeriod: 30n
warmStorageDefaultLockupPeriod;if (const newCDNDataSetNeeded: boolean
newCDNDataSetNeeded) { let lockupNeeded: bigint
lockupNeeded += const cdnDataSetCreationCost: bigint
cdnDataSetCreationCost; let totalCostNeeded: bigint
totalCostNeeded += const cdnDataSetCreationCost: bigint
cdnDataSetCreationCost;}
// Get current approval status (what's already being used)const [const approval: operatorApprovals.OutputType
approval, const accountInfo: accounts.OutputType
accountInfo] = await var Promise: PromiseConstructor
Represents the completion of an asynchronous operation
Promise.PromiseConstructor.all<[Promise<operatorApprovals.OutputType>, Promise<accounts.OutputType>]>(values: [Promise<operatorApprovals.OutputType>, Promise<accounts.OutputType>]): Promise<[operatorApprovals.OutputType, accounts.OutputType]> (+1 overload)
Creates a Promise that is resolved with an array of results when all of the provided Promises
resolve, or rejected when any Promise is rejected.
all([ const synapse: Synapse
synapse.Synapse.payments: PaymentsService
payments.PaymentsService.serviceApproval(options?: { service?: Address; token?: TokenIdentifier;}): Promise<operatorApprovals.OutputType>
serviceApproval(), const synapse: Synapse
synapse.Synapse.payments: PaymentsService
payments.PaymentsService.accountInfo(options?: { token?: TokenIdentifier;}): Promise<accounts.OutputType>
accountInfo(),]);
// Calculate cumulative allowances: existing usage + new requirements// This ensures the operator can spend for ALL your datasetsconst const lockupAllowanceNeeded: bigint
lockupAllowanceNeeded = const approval: operatorApprovals.OutputType
approval.lockupUsage: bigint
lockupUsage + let lockupNeeded: bigint
lockupNeeded;const const rateAllowanceNeeded: bigint
rateAllowanceNeeded = const approval: operatorApprovals.OutputType
approval.rateUsage: bigint
rateUsage + const pricePerEpoch: bigint
pricePerEpoch;
var console: Console
console.Console.log(...data: any[]): void
The console.log() static method outputs a message to the console.
log("New lockup needed:", let lockupNeeded: bigint
lockupNeeded);var console: Console
console.Console.log(...data: any[]): void
The console.log() static method outputs a message to the console.
log("Cumulative lockup allowance needed:", const lockupAllowanceNeeded: bigint
lockupAllowanceNeeded);var console: Console
console.Console.log(...data: any[]): void
The console.log() static method outputs a message to the console.
log("Cumulative rate allowance needed:", const rateAllowanceNeeded: bigint
rateAllowanceNeeded);Step 3: Fund Your Account
Section titled “Step 3: Fund Your Account”Check balances, calculate deposit amount, and execute the appropriate transaction:
// Calculate deposit amount neededconst const depositAmountNeeded: bigint
depositAmountNeeded = const totalCostNeeded: bigint
totalCostNeeded > const accountInfo: accounts.OutputType
accountInfo.availableFunds: bigint
availableFunds ? const totalCostNeeded: bigint
totalCostNeeded - const accountInfo: accounts.OutputType
accountInfo.availableFunds: bigint
availableFunds : 0n;
// Check if allowances are sufficientconst const sufficient: boolean
sufficient = const rateAllowanceNeeded: bigint
rateAllowanceNeeded <= const approval: operatorApprovals.OutputType
approval.rateAllowance: bigint
rateAllowance && const lockupAllowanceNeeded: bigint
lockupAllowanceNeeded <= const approval: operatorApprovals.OutputType
approval.lockupAllowance: bigint
lockupAllowance;
// Verify wallet balanceconst const walletBalance: bigint
walletBalance = await const synapse: Synapse
synapse.Synapse.payments: PaymentsService
payments.PaymentsService.walletBalance(options?: { token?: TokenIdentifier;}): Promise<bigint>
walletBalance({ token?: string
token: const TOKENS: { readonly USDFC: "USDFC"; readonly FIL: "FIL";}
TOKENS.type USDFC: "USDFC"
USDFC });if (const walletBalance: bigint
walletBalance < const depositAmountNeeded: bigint
depositAmountNeeded) { throw new var Error: ErrorConstructornew (message?: string, options?: ErrorOptions) => Error (+1 overload)
Error("Insufficient USDFC balance in wallet");}
// Execute appropriate transactionif (!const sufficient: boolean
sufficient && const depositAmountNeeded: bigint
depositAmountNeeded > 0n) { // Need both deposit and approval await const synapse: Synapse
synapse.Synapse.payments: PaymentsService
payments.PaymentsService.depositWithPermitAndApproveOperator(options: { amount: TokenAmount; operator?: Address; rateAllowance?: TokenAmount; lockupAllowance?: TokenAmount; maxLockupPeriod?: bigint; deadline?: bigint; token?: TokenIdentifier;}): Promise<Hash>
depositWithPermitAndApproveOperator({ amount: bigint
amount: const depositAmountNeeded: bigint
depositAmountNeeded });} else if (!const sufficient: boolean
sufficient) { // Only need approval update await const synapse: Synapse
synapse.Synapse.payments: PaymentsService
payments.PaymentsService.approveService(options?: { service?: Address; rateAllowance?: TokenAmount; lockupAllowance?: TokenAmount; maxLockupPeriod?: TokenAmount; token?: TokenIdentifier;}): Promise<Hash>
approveService();} else if (const depositAmountNeeded: bigint
depositAmountNeeded > 0n) { // Only need deposit await const synapse: Synapse
synapse.Synapse.payments: PaymentsService
payments.PaymentsService.depositWithPermit(options: { amount: TokenAmount; token?: TokenIdentifier; deadline?: bigint;}): Promise<Hash>
depositWithPermit({ amount: bigint
amount: const depositAmountNeeded: bigint
depositAmountNeeded });}
var console: Console
console.Console.log(...data: any[]): void
The console.log() static method outputs a message to the console.
log("Account funded successfully");Next Steps
Section titled “Next Steps”- Storage Operations - Storage concepts and workflows
- Storage Context - Contexts and data sets