Sizing the pool

How many nodes, which instance type, how many cache disks and how big: all of it follows from the volumes the pool has to serve. Put the workload in and the configuration comes out, along with what it costs against provisioned block storage:

5,000 GB
27 volumes

3 nodes × 9 volumes each · 10 × 484 GB cache disks per node

125 MB/s
3,000 IOPS

27,000 IOPS per node · stripe carries 30,000

Advanced

Capacity

80 %
30 % / month

1.5 TB rewritten / month per volume

10 % of capacity

500 GB per volume · 13,500 GB total

Throughputper volume

125 MB/s

5 TB written / month

125 MB/s

328.5 TB read / month

10 %
0.5 cores

7.5 cores per node

1 cores
4 GiB

31.3 GiB per node

10 disks

30,000 IOPS and 1,250 MB/s a node · 484 GB a disk, all of it on the free baseline

10 %

3 nodes at $1,275/mo — already the cheapest layout

Node architecture
Instance typesall 34

59%$10,750/mo saved

cheaper than EBS gp3, for 135 TB provisioned

backedblock.io$7,475/mo
EBS gp3$18,225/mo
Show calculation

backedblock.io

Compute
$1,275
Object storage$2,484
EBS cache$1,080
Cache performance$0.00
PUT requests$877
GET requests$355
Snapshots$1,404
Total$7,475

EBS gp3

Provisioned capacity$10,800
Throughput$0.00
IOPS$0.00
Snapshots$7,425
Total$18,225

Configuration for one pool

The sized values behind the estimate, as Terraform and StorageClass parameters. Everything not listed keeps its default.

hcl
# pool/main.tf - the sized values only; the rest of the module block
# is unchanged (see /docs/single-pool).

nodes_count           = 3
nodes_instance_type   = "m8gb.2xlarge"   # 8 vCPU, 32 GiB

raid_level            = 0
nvme_node_disks_count = 10
max_volumes_count     = 10

r_cache_size_in_mib   = 437737   # per disk; the volumes' whole footprint
rw_cache_size_in_mib  = 218869   # per disk; dirty data inside it

ebs_volumes = [{
  size       = 460
  type       = "gp3"
  iops       = 3000  # 30,000 IOPS across the stripe, on the free baseline
  throughput = 125   # 1,250 MB/s across the stripe, on the free baseline
  count      = 10
}]
yaml
# StorageClass parameters, or the matching storageclass.* Helm values
# (see /docs/storage-class).

parameters:
  ratio_cache_r_cache_size: "0.1"
  ratio_cache_rw_cache_size: "0.05"
  max_cache_r_cache_size: "476837"     # 466 GiB at 5,000 GB
  max_cache_rw_cache_size: "238419"    # inside the read cache, not beside it
  qos_r_mbytes_per_sec: "125"
  qos_w_mbytes_per_sec: "125"
  qos_rw_mbytes_per_sec: "125"   # the peak either direction reaches, not their sum
  qos_rw_ios_per_sec: "3000"      # combined; there is no per-direction IOPS cap

The two blocks at the end are the values to carry into the blueprint: the first into the pool's main.tf, the second into the StorageClass the volumes are created from. Everything they do not mention keeps its default.

Where the numbers come from:

  • Storage compute — the cores, memory and bandwidth a node needs, and why it is never fewer than three nodes.
  • Caching and tiering — the cache disks, the two pool cache sizes and the StorageClass ratios and ceilings.

The per-volume CPU and memory coefficients under Advanced are averages, not constants. Measure them on the pool you build and put your own numbers in — the figures move with volume size, encryption, compression and load.