How Much Does a Disposable VM Cost? A Per-Minute Billing Estimator for Batch Workloads
LiteVPS bills disposable VMs per minute at price_hourly / 60, caps each VM at its monthly price, and keeps charging while a VM is stopped. This article includes a tested estimator script for pricing a single sandbox or a whole batch.
A disposable VM on LiteVPS costs its plan's hourly price divided by 60 for every minute it exists, including minutes spent stopped. The monthly price on the pricing page is a per-VM cap for a calendar month, not a flat subscription, so a VM that lives a few minutes costs only those minutes. Creating a VM requires a prepaid balance of at least $1.00 and sets aside the estimated first-hour cost at create time, which is returned only if provisioning fails. Destroying the VM, or letting its TTL expire, stops the meter. The estimator below reproduces these numbers exactly.
What does the meter actually charge?
Per-minute metering comes from the plan's hourly price divided by 60. The following numbers are the live public plans as of August 10, 2026, from GET /api/pricing:
| Plan | vCPU | RAM | Disk | $/hour | $/minute | $/month cap |
|---|---|---|---|---|---|---|
| Lite1 | 1 | 1 GB | 20 GB | $0.01 | $0.000167 | $7.30 |
| Medium1 | 2 | 2 GB | 25 GB | $0.02 | $0.000333 | $14.60 |
| Performance1 | 4 | 8 GB | 30 GB | $0.05 | $0.000833 | $36.50 |
Attaching a public IPv4 adds $0.00274/hour (cap $2.00/month) to both the metered rate and the create-time reservation. The per-minute figures above are price_hourly / 60, matching the meter's calculation of (price_hourly / 60) × minutes.
Three behaviors decide most of what a disposable VM actually costs:
- Running and stopped VMs both accrue. A stopped VM still holds its disk and a reserved slot on the host, so it keeps metering until it is destroyed.
- Destroying stops the meter. Deleting the VM (or letting its server-side TTL expire) bills any accrued-but-not-yet-flushed minutes and then stops charging. Billing is accumulated per minute and written to your balance about every ten minutes; each day's usage is rolled up into a single ledger entry.
- The monthly price is a cap. Once a VM has accrued its monthly price within a calendar month, charges stop for that VM and reset on the first of the next month. A VM that lives the full month never costs more than the monthly figure.
The create-time costs that are easy to miss
The per-minute rate is only part of the picture. When the API provisions a VM it also:
- Requires a minimum prepaid balance of $1.00. The create call returns
HTTP 402when the balance is below that. - Sets aside the estimated first-hour cost at create. That is the plan's hourly price (floor $0.001) plus the public IPv4 add-on if requested, deducted after placement is validated. It is returned only if provisioning fails. Budget roughly one hour's cost per VM, on top of the metered usage.
- Checks per-account limits. Accounts start with a limit of one concurrent VM; batch and parallel use requires raising that limit. A batch create call is also capped by the
max_batch_sizesetting, which defaults to 10.
Every authenticated response includes an X-Balance-Remaining header, so an agent can watch the meter after each API call without polling GET /api/billing/balance.
A tested estimator
The script below reproduces the meter: per-minute rate, the monthly cap, the running-plus-stopped accumulation, and the create-time reservation. It is dependency-free (Python 3 standard library only) and hardcodes the live prices above so you can check it against the current GET /api/pricing response.
#!/usr/bin/env python3
"""Estimate the cost of a disposable VM (or a batch of them) on LiteVPS.
Billing model, verified against https://api.litevps.dev/api/pricing and the
LiteVPS billing implementation:
* Usage is metered per minute at price_hourly / 60.
* The monthly price is a per-VM cap on what one VM can accrue in a calendar
month. A VM that lives the whole month is capped at the monthly price.
* VMs in "running" OR "stopped" state keep accruing. Destroy the VM (or let
its TTL expire) to stop billing; the last partial minutes are billed when
the VM is destroyed.
* Creating a VM requires a prepaid balance of at least $1.00 and sets aside
the estimated first-hour cost at create time (price_hourly, floor $0.001,
plus the public IPv4 add-on if requested). That amount is returned only if
provisioning fails.
Run `python3 estimate_disposable_vm_cost.py --selftest` to check the numbers
against the assertions below.
"""
import argparse
import sys
PLANS = {
# slug: (price hourly USD, price monthly USD) — live GET /api/pricing
"lite1": (0.01, 7.30),
"medium1": (0.02, 14.60),
"performance1": (0.05, 36.50),
}
PUBLIC_IPV4_HOURLY = 0.00274 # add-on, USD/hour
PUBLIC_IPV4_MONTHLY = 2.00 # add-on, USD/month cap
MIN_CREATE_BALANCE = 1.00 # USD — required before the platform provisions
RESERVATION_FLOOR = 0.001 # USD — minimum first-hour estimate set aside
def per_minute(hourly):
return hourly / 60.0
def metered_cost(hourly, monthly, minutes):
"""Metered USD for one VM that lived `minutes` in the current calendar month."""
raw = per_minute(hourly) * minutes
if monthly > 0:
return min(raw, monthly)
return raw
def reservation(hourly, ipv4):
"""USD set aside at create (estimated first-hour cost, add-on included)."""
est = max(hourly, RESERVATION_FLOOR)
if ipv4:
est += PUBLIC_IPV4_HOURLY
return est
def min_balance_for(vms, reservations_per_vm):
"""Smallest prepaid balance that passes the API's create checks."""
return max(MIN_CREATE_BALANCE, vms * reservations_per_vm)
def estimate(plan, minutes, vms=1, stopped_minutes=0, ipv4=False,
monthly_charged=0.0):
hourly, monthly = PLANS[plan]
rate = per_minute(hourly)
total_minutes = minutes + stopped_minutes
acc = 0.0
for _ in range(vms):
raw = rate * total_minutes
remaining = max(monthly - monthly_charged, 0.0)
acc += min(raw, remaining)
metered = acc
reserv = reservation(hourly, ipv4)
reservations_total = reserv * vms
balance_impact = metered + reservations_total
needed = min_balance_for(vms, reserv)
return {
"plan": plan,
"hourly": hourly,
"monthly_cap": monthly,
"per_minute": rate,
"reservation_per_vm": reserv,
"vms": vms,
"runtime_minutes": minutes,
"stopped_minutes": stopped_minutes,
"metered": metered,
"reservations_total": reservations_total,
"balance_impact": balance_impact,
"min_balance_to_create": needed,
"ipv4": ipv4,
}
def render(r):
line = (
f"{r['plan']}: {r['per_minute']:.6f} $/min "
f"({r['hourly']:.4f} $/h, cap {r['monthly_cap']:.2f} $/month)"
)
print(line)
print(f" VMs: {r['vms']} x {r['runtime_minutes']}m runtime"
f" + {r['stopped_minutes']}m stopped"
+ (" + public IPv4 add-on" if r["ipv4"] else ""))
print(f" set aside at create: {r['reservation_per_vm']:.4f} $/VM"
f" x {r['vms']} = {r['reservations_total']:.4f} $")
print(f" metered usage: {r['metered']:.4f} $")
print(f" total balance impact: {r['balance_impact']:.4f} $")
print(f" minimum prepaid balance to create: {r['min_balance_to_create']:.2f} $")
def selftest():
def close(a, b, tol=1e-6):
assert abs(a - b) < tol, f"{a} != {b}"
# Per-minute rate on Lite1 is $0.01 / 60.
close(per_minute(0.01), 0.01 / 60.0)
# 60 minutes on Lite1 meters exactly $0.01.
close(metered_cost(0.01, 7.30, 60), 0.01)
# 100000 minutes (~69 days) would meter $16.67, but is capped at $7.30.
close(metered_cost(0.01, 7.30, 100000), 7.30)
# No cap -> no limit (cap 0 disables it).
close(metered_cost(0.01, 0, 100000), 100000 * (0.01 / 60.0))
# Reservation is the hourly price (floor $0.001).
close(reservation(0.01, False), 0.01)
close(reservation(0.001, False), 0.001)
# Public IPv4 add-on raises both the metered rate and the reservation.
close(per_minute(0.01 + PUBLIC_IPV4_HOURLY), (0.01274) / 60.0)
close(reservation(0.01, True), 0.01274)
# A 30-minute batch of 3 Lite1 VMs.
r = estimate("lite1", minutes=30, vms=3)
close(r["metered"], 3 * (0.01 / 60.0) * 30) # 0.015
close(r["reservations_total"], 0.03)
close(r["balance_impact"], 0.045)
# 60m running + 30m stopped meters the same as 90m running.
close(estimate("lite1", minutes=60, stopped_minutes=30)["metered"],
estimate("lite1", minutes=90)["metered"])
# Cap applies per calendar month; prior charges reduce the remaining cap.
close(metered_cost(0.01, 7.30, 43800) - metered_cost(0.01, 7.30, 30000),
metered_cost(0.01, 7.30, 13800))
close(estimate("lite1", minutes=100000, monthly_charged=0.0)["metered"], 7.30)
# Minimum create balance is at least $1.00 and covers all reservations.
close(min_balance_for(1, 0.01), 1.00)
close(min_balance_for(3, 0.01), 1.00)
close(min_balance_for(300, 0.01), 3.00)
print("selftest: all assertions passed")
def main(argv):
parser = argparse.ArgumentParser(
description="Estimate the cost of disposable VMs on LiteVPS.")
parser.add_argument("--plan", choices=sorted(PLANS), default="lite1")
parser.add_argument("--minutes", type=int, default=60,
help="runtime minutes per VM")
parser.add_argument("--vms", type=int, default=1)
parser.add_argument("--stopped-minutes", type=int, default=0,
help="minutes each VM exists while stopped (still billed)")
parser.add_argument("--ipv4", action="store_true",
help="attach the public IPv4 add-on")
parser.add_argument("--monthly-charged", type=float, default=0.0,
help="already-charged usage this calendar month per VM")
parser.add_argument("--selftest", action="store_true")
args = parser.parse_args(argv)
if args.selftest:
selftest()
return 0
render(estimate(args.plan, args.minutes, vms=args.vms,
stopped_minutes=args.stopped_minutes, ipv4=args.ipv4,
monthly_charged=args.monthly_charged))
return 0
if __name__ == "__main__":
sys.exit(main(sys.argv[1:]))
Run the self-test to confirm the assertions still hold for your copy, then estimate a workload:
python3 estimate_disposable_vm_cost.py --selftest
python3 estimate_disposable_vm_cost.py --plan lite1 --minutes 30 --vms 3
Output for the batch example:
lite1: 0.000167 $/min (0.0100 $/h, cap 7.30 $/month)
VMs: 3 x 30m runtime + 0m stopped
set aside at create: 0.0100 $/VM x 3 = 0.0300 $
metered usage: 0.0150 $
total balance impact: 0.0450 $
minimum prepaid balance to create: 1.00 $
The batch example assumes your account's per-VM limit and max_batch_size allow three VMs; both defaults start lower for new accounts.
Worked examples
| Scenario | Set aside at create | Metered | Balance impact | Minimum balance |
|---|---|---|---|---|
| 1 × Lite1 for 30 minutes | $0.01 | $0.005 | $0.015 | $1.00 |
| 1 × Medium1, 45 min, public IPv4 | $0.0227 | $0.015 | $0.0377 | $1.00 |
| 1 × Performance1 for 2 hours | $0.05 | $0.10 | $0.15 | $1.00 |
| 1 × Lite1 for a full month | $0.01 | $7.30 | $7.31 | $1.00 |
The last row shows the cap at work: a whole month of metering never exceeds the monthly figure, so the reservation is the only thing pushing the month slightly past the listed $7.30.
When should you use this estimator?
- Budgeting disposable batch jobs, integration tests, or temporary sandboxes before you run them.
- Comparing the cost of a short-lived VM against a container or a serverless function for the same task.
- Planning batch runs, where the per-VM reservation multiplies and the create call checks your $1.00 minimum and per-account limit.
When should you not use this estimator?
- For always-on workloads. Once a VM crosses roughly a month of uptime the cap applies and the monthly price is the number that matters.
- As a substitute for the live pricing endpoint. Prices and limits can change; re-check
GET /api/pricingand themax_batch_sizeand per-account limit settings before relying on exact figures. - It models compute minutes, the public IPv4 add-on, and the create-time reservation only. It does not include other products such as snapshots.
What should you read next?
A safe lifecycle pattern for ephemeral compute shows the create-wait-work-delete controller this estimator pairs with. How to give an AI agent a disposable Linux sandbox covers the isolation boundary, and VPS, container, or serverless function for agent code execution? helps decide whether a VM is warranted at all. See the LiteVPS platform guide and API reference for the create, TTL, and billing endpoints.
Methodology note
The per-minute formula, monthly cap, running-and-stopped accrual, delete-time billing flush, $1.00 minimum balance, create-time first-hour reservation with refund on provisioning failure, default max_batch_size of 10, per-account VM limit default of 1, and X-Balance-Remaining header were checked against the LiteVPS implementation on August 10, 2026. Plan prices were read from the live GET /api/pricing endpoint on the same date and may change.