Storage Provider Tiers
Not every storage provider (SP) on the Filecoin network participates in the Filecoin Onchain Cloud (FOC) on equal footing. To deliver a production-grade quality of service, the Filecoin Warm Storage Service (FWSS) maintains an on-chain set of approved providers, and a subset of those are additionally endorsed for a higher service tier.
This page explains what each tier means, how a provider moves between tiers, and how the tiers affect provider selection and replica placement in the Synapse SDK.
Provider Tiers at a Glance
Section titled “Provider Tiers at a Glance”| Tier | Qualification | Selected by the SDK? |
|---|---|---|
| Non-approved | Registered in the SP Registry but not in the FWSS approved set | No |
| Approved | Meets published quality criteria; added to the on-chain approved set | Yes, for secondary copies |
| Endorsed | Approved, plus additional operational commitments | Yes, and always used for the primary copy |
Non-Approved Providers
Section titled “Non-Approved Providers”A non-approved provider is registered in the ServiceProviderRegistry but is not in the FWSS approved-provider set. Non-approved providers:
- Are not selected by the Synapse SDK for normal storage routing. Uploads through
synapse.storagewill never place data with them automatically. - May still be actively tested by Dealbot, the FOC quality-monitoring bot, in order to qualify for approval.
- Can still be used explicitly if you pass their
providerIdto lower-level APIs, though this bypasses the quality vetting that approval represents.
It is possible for a provider to be removed from the approved list. Removal does not deactivate existing storage deals and does not prevent further interaction with that provider via the SDK but removal may be an indication of a lowering of service quality.
Approved Providers
Section titled “Approved Providers”An approved provider is a member of the on-chain FWSS approved-provider set. Approval means the provider has demonstrated, through continuous automated testing, that it meets the published acceptance criteria for storage success, data retention, and retrieval success.
Approved providers:
- Are eligible for selection by the Synapse SDK. In the default flow, approved-only providers receive secondary copies, while the primary copy goes to an endorsed provider.
- Are continuously monitored by Dealbot. A provider that stops meeting the criteria can be removed from the approved set.
How Providers Become Approved
Section titled “How Providers Become Approved”Qualification is measured automatically, but the on-chain change is applied manually:
- Automated qualification: Dealbot continuously runs storage, retention, and retrieval checks against providers (including non-approved ones seeking approval). The full acceptance criteria and measurement methodology are published in the Dealbot production configuration and approval methodology.
- Manual review and on-chain change: Satisfying the Dealbot criteria makes a provider eligible, but approval is not automatic. When Dealbot signals that a provider should be added or removed, a review is opened and the change is proposed for signing and execution by the SAFE multisig that controls the approved set.
Approval and removal reviews are currently tracked publicly as GitHub issues: see the open and past SP approval reviews and the review template that documents what each review covers.
Endorsed Providers
Section titled “Endorsed Providers”Endorsement is a higher service tier layered on top of approval. An endorsed provider is an approved provider that has additionally made operational commitments beyond the automated quality checks, such as service continuity, response times for support and incident handling, and related operational expectations.
Key properties:
- Endorsement is granted and removed manually; there is no automated path to endorsement.
- The endorsed set is recorded on-chain, separately from the approved set.
- The Synapse SDK places at least one replica of your data with an endorsed provider by default (the primary copy), so every upload benefits from the higher tier.
Possible Tier Combinations
Section titled “Possible Tier Combinations”Approval and endorsement are independent on-chain sets, so these combinations are possible:
| State | Meaning |
|---|---|
| Approved + endorsed | The highest tier. Eligible for all copies and preferred for the primary copy. |
| Approved only | Eligible for selection as a secondary copy. |
| Neither | Not selected by the SDK. May be under Dealbot evaluation to qualify. |
| Endorsed only | Technically possible, but in practice never used as all endorsed SPs are expected to also be approved. |
On-Chain Source of Truth
Section titled “On-Chain Source of Truth”Both lists are recorded on-chain in the FilOzone/filecoin-services contracts. GitHub issues, Dealbot dashboards, and this documentation are all commentary; the contracts are authoritative.
The approved set lives in the FilecoinWarmStorageService contract, which maintains the list of approved provider IDs and exposes owner-only addApprovedProvider and removeApprovedProvider functions (this owner is the SAFE multisig mentioned above). To read the list, query getApprovedProviders on the companion FilecoinWarmStorageServiceStateView contract, which serves all FWSS read operations.
The endorsed set is a standalone ProviderIdSet contract (listed as “Endorsements” in the address tables), also owner-controlled. Query getProviderIds to read the full list or containsProviderId to check a single provider.
Deployed addresses for both contracts on mainnet and calibration, with block explorer links, are on the Contract Addresses page.
You can also query both sets with @filoz/synapse-core, which wraps these contract reads:
import { function paginate<T>(getPage: paginate.GetPage<T>, options?: paginate.OptionsType): paginate.OutputType<T>paginate } from "@filoz/synapse-core"
import { function getApprovedProviderIds(client: Client<Transport, Chain>, options?: getApprovedProviderIds.OptionsType): Promise<getApprovedProviderIds.OutputType>getApprovedProviderIds } from "@filoz/synapse-core/warm-storage"
import { function getEndorsedProviderIds(client: Client<Transport, Chain>, options?: getEndorsedProviderIds.OptionsType): Promise<getEndorsedProviderIds.OutputType>getEndorsedProviderIds } from "@filoz/synapse-core/endorsements"
const const approved: bigint[]approved = await var Array: ArrayConstructorArray.ArrayConstructor.fromAsync<bigint>(iterableOrArrayLike: AsyncIterable<bigint> | Iterable<bigint | PromiseLike<bigint>> | ArrayLike<bigint | PromiseLike<bigint>>): Promise<bigint[]> (+1 overload)Creates an array from an async iterator or iterable object.fromAsync(
paginate<bigint>(getPage: paginate.GetPage<bigint>, options?: paginate.OptionsType): paginate.OutputType<bigint>paginate(({ cursor: bigintcursor }) => function getApprovedProviderIds(client: Client<Transport, Chain>, options?: getApprovedProviderIds.OptionsType): Promise<getApprovedProviderIds.OutputType>getApprovedProviderIds(const publicClient: {
account: undefined;
batch?: {
multicall?: boolean | Prettify<MulticallBatchOptions> | undefined;
} | undefined;
cacheTime: number;
ccipRead?: false | {
request?: (parameters: CcipRequestParameters) => Promise<CcipRequestReturnType>;
} | undefined;
chain: FilecoinChain;
dataSuffix?: DataSuffix | undefined;
experimental_blockTag?: BlockTag | undefined;
... 70 more ...;
extend: <const client extends {
...;
} & ExactPartial<...>>(fn: (client: Client<...>) => client) => Client<...>;
}
publicClient, { cursor?: bigint | undefinedcursor }))
)
const const endorsed: getEndorsedProviderIds.OutputTypeendorsed = await function getEndorsedProviderIds(client: Client<Transport, Chain>, options?: getEndorsedProviderIds.OptionsType): Promise<getEndorsedProviderIds.OutputType>getEndorsedProviderIds(const publicClient: {
account: undefined;
batch?: {
multicall?: boolean | Prettify<MulticallBatchOptions> | undefined;
} | undefined;
cacheTime: number;
ccipRead?: false | {
request?: (parameters: CcipRequestParameters) => Promise<CcipRequestReturnType>;
} | undefined;
chain: FilecoinChain;
dataSuffix?: DataSuffix | undefined;
experimental_blockTag?: BlockTag | undefined;
... 70 more ...;
extend: <const client extends {
...;
} & ExactPartial<...>>(fn: (client: Client<...>) => client) => Client<...>;
}
publicClient)
var console: Consoleconsole.Console.log(...data: any[]): voidThe **`console.log()`** static method outputs a message to the console.
[MDN Reference](https://developer.mozilla.org/docs/Web/API/console/log_static)log("Approved provider IDs:", const approved: bigint[]approved)
var console: Consoleconsole.Console.log(...data: any[]): voidThe **`console.log()`** static method outputs a message to the console.
[MDN Reference](https://developer.mozilla.org/docs/Web/API/console/log_static)log("Endorsed provider IDs:", const endorsed: getEndorsedProviderIds.OutputTypeendorsed)How Tiers Affect Synapse SDK Provider Selection
Section titled “How Tiers Affect Synapse SDK Provider Selection”When you upload through the SDK without specifying providers, the upload pipeline selects providers by tier:
- The primary copy (the one you upload directly) goes to an endorsed provider.
- Secondary copies are pulled from the primary via SP-to-SP transfer and can go to any approved provider.
- Non-approved providers are never selected automatically.
Before finalizing a selection, the SDK also verifies the candidate provider is reachable via a ping test and falls back to the next candidate if it is not. See Storage Operations for the full selection rules, including data set reuse.
Further Reading
Section titled “Further Reading”- Dealbot approval methodology and acceptance criteria
- SP approval reviews on GitHub
- Upload Pipeline for how copies are placed
- Storage Operations for data set and provider selection details