Build1 publisher3 min readPublished
Two constant tables set the derating in this TypeScript battery runtime engine
A dev.to engine folds Peukert's law, inverter idle draw and depth-of-discharge into one deterministic function. Its per-chemistry exponent and hour-rating tables decide the correction, and one entry returns more than nameplate.
The Engineer · Build desk

What happened
- A dev.to walkthrough argues that nominal runtime formulas overestimate battery backup endurance by 30 to 50 percent under real load, and blames Peukert's rate-capacity effect, inverter idle draw and depth-of-discharge limits.
- The engine it publishes hard-codes one Peukert exponent per chemistry: 1.03 for LiFePO4, 1.05 for lithium-ion, 1.15 for AGM and 1.30 for flooded lead-acid.
- A second table sets the benchmark hour rating used to derive rated discharge current, at 20 hours for both lead-acid chemistries and 1.0 hour for both lithium ones.
- AC load is converted by dividing by inverter efficiency, which the article puts at 0.88 to 0.94, and then adding a fixed tare figure once, whatever the size of the appliance.
- The published listing breaks off mid-expression inside the Peukert factor, so how the derating composes into the returned runtimeHours is not shown.
Compiled by The EngineerSomething wrong?How this is made
Why it matters
- constraint Every term here is multiplicative, so changing inverter efficiency or the depth-of-discharge limit rescales the Peukert result as well, and no single stage can be validated against a measured runtime in isolation.
- decision Adopting the engine means adopting its hour-rating table, so anyone modelling LiFePO4 has to check what discharge rate the manufacturer's Ah figure was measured at before the output means anything.
- contradiction The article gives tare as 15 to 55W in its opening and 15 to 45W in its inverter section, and where you land in that range decides whether idle draw is a minority or a majority of drain on a small overnight load.
- capability Because the result exposes peukertDeratingFactor and effectiveDischargeAmps next to the runtime, a reviewer can recompute each stage by hand instead of accepting one number, which is how the figures below were checked.
The factor in the listing is (I_rated / I_actual)^(k-1), applied to capacity, with I_rated computed as nominalCapacityAh divided by the chemistry's benchmark hour rating [8]. Rearrange it. Multiply capacity C by that factor, divide by the actual current I, substitute I_rated = C/H, and you get t = H (C / (I H))^k, the equation the article attributes to Wilhelm Peukert in 1897 [4][5]. The correction is the published law.
The two Record tables carry the assumptions. The code takes one value per chemistry out of ranges the article gives as 1.25 to 1.40 for flooded lead-acid and 1.02 to 1.05 for LiFePO4 [5][6]. It does the same for the benchmark rating: the article says LiFePO4 nameplates are typically quoted somewhere between 1 and 5 hours, and the table takes the shortest end [5][7].
That choice has a direction. At H = 1, a 200 Ah pack has a rated current of 200 A. Pull 29 A from it and the factor comes out as (200/29.26)^0.03, about 1.06, so the engine returns roughly six percent more energy than the nameplate [4]. For a pack whose datasheet Ah figure was measured at a 5-hour rate, those six percent are an artefact of the hour-rating table.
The 1.30 exponent for flooded lead-acid produces the largest derating. Take 200 Ah at 12 V, a 50 percent depth-of-discharge limit, 300 W of AC load, 0.92 inverter efficiency and 25 W of tare, which are the example values in the interface comments [14]. Naive division gives 2,400 Wh over 300 W, or eight hours. Composing the three corrections multiplicatively: total draw 351 W, so 29.26 A; rated current 10 A; factor (10/29.26)^0.30 = 0.725; usable energy 1,200 Wh derated to 870 Wh; runtime 2.48 hours [3]. That is 69 percent under the naive figure, past the top of the 30 to 50 percent band the article opens with [1]. The article does not say which baseline that band is measured against, so the two numbers are not strictly comparable.
The tare claim is the softest part. The article says that at low loads, such as a 30 W CPAP on a 3,000 W inverter, tare is more than half of total battery drain [10]. Run its own defaults: the appliance pulls 30/0.92 = 32.6 W from the battery, the inverter pulls 25 W, and idle is 43 percent of the 57.6 W total [1][9]. Tare has to exceed about 33 W before it is the majority [2]. That is inside both of the bands the article quotes, and well above the 25 W in its own interface comment [14].
For any of this to transfer to a specific bank you need two things the tables currently supply by chemistry: the Peukert exponent measured on those cells, and the hour rating the manufacturer actually used to print the Ah figure. The first moves the derating factor; the second moves the rated current the factor is measured against. Both are guesses until someone reads the discharge table.
What to watch
- Whether the completed listing applies the Peukert factor to nominal energy or to the depth-of-discharge-limited figure, and what conditions the warnings array actually fires on.
- Whether the exponent tables move from one constant per chemistry to a per-battery value read off a manufacturer discharge table. Every number the engine returns would change.
- Whether the LiFePO4 hour rating stays at 1.0 or moves toward the 5-hour end of the range the article itself cites.