BYTES_PER_GB
BYTES_PER_GB = 1000000000
Bytes in a gigabyte, decimal, as every provider bills.
Providers price per GB and mean 10^9, not 2^30. Using the binary value would understate a bill by 7.4%.
What one provider charges, and what it gives away.
Object storage is priced on three axes and only one of them is bytes. Storage is charged per gigabyte-month, writes are charged per million (S3 calls them PUT, R2 calls them Class A), and reads are charged per million (GET, Class B). A backup system is unusual in that it writes constantly and reads almost never, so the write axis is the one that decides the bill - and it depends on the flush interval rather than on the size of the site.
The consequence is stated in one line: at a fifteen-second interval a site of any size performs about 201,635 writes a month, which is a fifth of R2's free allowance and about a dollar a month on S3. On R2 the free tier absorbs the whole thing; on S3 that dollar is a floor a small site cannot get under.
These are shipped defaults, not a promise. Published list prices as read on 2026-08-20, for
R2 and for S3 Standard in us-east-1. A provider changes its prices and a different region
charges differently, so every field is overridable and the estimate names the table it used.
__construct(string $id, string $label, float $storagePerGbMonth, float $writesPerMillion, float $readsPerMillion, float $egressPerGb = 0.0, int $freeStorageBytes = 0, int $freeWrites = 0, int $freeReads = 0) : mixed
Constructs a table.
| string | $id | Short lowercase identifier, matching the storage provider's own id where there is one. |
| string | $label | Human-readable name. |
| float | $storagePerGbMonth | Dollars per gigabyte-month of stored data. |
| float | $writesPerMillion | Dollars per million write requests. |
| float | $readsPerMillion | Dollars per million read requests. |
| float | $egressPerGb | Dollars per gigabyte of egress. Zero on R2, which is the reason a restore is free there. |
| int | $freeStorageBytes | Stored bytes included at no charge each month. |
| int | $freeWrites | Write requests included at no charge each month. |
| int | $freeReads | Read requests included at no charge each month. |
When the id is empty or any price is negative.
s3() : \Drupal\strata\Estimate\PriceTable
AWS S3 Standard, us-east-1.
No free allowance beyond the first-year introductory tier, which is not modelled because an estimate that expires after twelve months is worse than one that does not exist.
The table.
s3InfrequentAccess() : \Drupal\strata\Estimate\PriceTable
AWS S3 Standard-Infrequent Access.
Where file blocks belong. Cheaper to keep and dearer to read, which is the right trade for content that is written once and read only during a restore.
The table.
local() : \Drupal\strata\Estimate\PriceTable
A store on the server's own disk.
Priced at zero rather than excluded, so the estimator can compare a local target against a remote one without a special case. Disk is not free, but its cost is not per-request and is not something this module can read.
The table.
forProvider(string $id) : self
The table to cost a storage provider with, falling back rather than raising.
Four tables are shipped and the provider select offers every registered submodule, so
azure, gcs, b2 and null all name a provider with no published prices - as does any id
an add-on registers. PriceTable::of() is the right shape for a caller naming a table it knows
exists; a caller naming whatever a site happens to have configured needs this one, because the
throw lands on the settings page the operator would use to change the provider back.
| string | $id | A storage provider id, which may be empty or unknown. |
The table for that provider, or the local one, which charges nothing.