throttled writes to CPU registers as root, and the tool it tells you to diagnose with does the same
Linux daemon for Intel CPU power limits and firmware-induced throttling.
At a glance
- What is it?
- A root daemon that periodically restores package power limits and a temperature target in MSR and MCHBAR registers after firmware resets them. Its shipped power values are explicitly not recommendations, its IccMax setting is an absolute limit rather than an offset, and the wheel installs only the command.
- Who is it for?
- throttled fits a laptop whose firmware repeatedly clamps power below what the hardware can sustain, on a machine you own and can reinstall, and where you have already confirmed the symptom with a read-only tool before changing anything. Three things to check first.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 4, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The README opens with a warning about hardware damage, and it should
The first callout in this README is marked as a caution and it is the most important paragraph in the document. `throttled` runs as root and writes directly to CPU and chipset registers, and incorrect power, temperature, voltage or current values can make a system unstable or damage hardware. The instruction that follows is to review the configuration for your CPU and cooling system before enabling the service.
The mechanism is narrow enough to state precisely. The daemon periodically restores the package power limits, PL1 and PL2, and the temperature target, writing them into MSR and MCHBAR registers after firmware or the embedded controller resets them. In other words it is fighting a firmware behaviour by rewriting the values the firmware just overwrote, on a timer, indefinitely.
That is the whole design, and it explains the risk. Nothing about the mechanism verifies that the value being restored is safe for the silicon in front of it, because the tool is restoring a number you supplied rather than measuring a thermal envelope.
The last commit was on 2026-10-04 and the repository is not archived, so this is being worked on. That is not a statement about whether the defaults are right for your machine, which is the only question that matters here.
The diagnostic command that confirms the problem also runs the control loop
The README tells you to confirm the problem before changing anything, and it names two read-only tools for that: s-tui and turbostat. It offers a third option, the monitor flag:
sudo throttled --monitor
sudo throttled --monitor 0.5
sudo throttled --debugThe monitor distinguishes thermal, power, current and cross-domain limits, and the debug mode reads back values that were written and prints CPU feature and thermal status information. Both look like the diagnostic you want.
The next paragraph is the one to read twice. Both commands run the control loop in the foreground, so the service has to be stopped first to avoid running two instances, and you press Ctrl+C when finished.
So the tool you are told to use to establish whether firmware is throttling your CPU is also the tool that writes registers, and using it means stopping the running daemon to do so. That is not a criticism of the design, which is reasonable for a diagnostic that shows live register state, but it does mean the read-only confirmation step and the active monitoring step are not the same activity, and a monitoring session is an intervention rather than an observation.
The shipped AC and battery values differ in three places, and the README disclaims them
The configuration lives at `/etc/throttled.conf` and holds separate AC and battery profiles. The defaults as shipped look like this:
[GENERAL]
Enabled: True
Autoreload: True
[AC]
Update_Rate_s: 5
PL1_Tdp_W: 44
PL1_Duration_s: 28
PL2_Tdp_W: 44
PL2_Duration_S: 0.002
Trip_Temp_C: 95
[BATTERY]
Update_Rate_s: 30
PL1_Tdp_W: 29
PL1_Duration_s: 28
PL2_Tdp_W: 44
PL2_Duration_S: 0.002
Trip_Temp_C: 85The two profiles differ in three fields and match in three. They differ in the update rate, 5 seconds on AC against 30 on battery, in the sustained package limit, 44 watts against 29, and in the trip temperature, 95 degrees against 85. They are identical in both duration fields and in the short-term limit.
What the README says about those numbers is the part to carry away: they are project defaults, not recommendations for every system, and you should check your processor limits and cooling capacity before changing them.
The autoreload flag means a valid edit to the file is picked up without restarting the service, which is convenient and also means a typo becomes effective on its own.
The two duration keys differ in case, and the naming drifts across sections
Look closely at the two duration keys in the configuration above. The sustained limit's window is written `PL1_Duration_s` with a lowercase trailing letter, and the short-term limit's window is written `PL2_Duration_S` with an uppercase one.
Two keys in the same block, referring to the same quantity in different units of the same schema, spelled with different case. Python's standard config parser treats option names case-insensitively by default, so both will be read, and the difference will not bite you. It will bite anyone who writes a config parser of their own, or who greps the file, and it is a small indicator of how the defaults came to look the way they do.
The naming is inconsistent at section level too. The general section uses capitalised words, `Enabled` and `Autoreload`, while the profile sections use keys built from separated words with mixed case inside them, `Update_Rate_s`, `PL1_Tdp_W`, `PL2_Duration_S`, `Trip_Temp_C`. Four different conventions in one INI file.
The sections themselves are extensible rather than fixed, which is the point of the file. Voltage offsets live in `[UNDERVOLT.AC]` and `[UNDERVOLT.BATTERY]`, current limits in `[ICCMAX.AC]` and `[ICCMAX.BATTERY]`, so the same two-profile split applies to every control the daemon exposes.
IccMax is an absolute current limit, and the undervolt floor is set by an 11-bit field
Two of the optional controls have failure modes that come purely from how their numbers are read.
IccMax values are absolute current limits in amperes, not offsets. The README says to inspect the system defaults with the monitor before enabling them. A configuration file where one setting is a target and a neighbouring one is a delta is a reliable source of a machine that limits current far below what it should, so the unit matters more here than in most settings.
Voltage offsets are the opposite case. They are configured independently per profile, only zero or negative millivolt values are accepted, and the floor is down to negative 1000 millivolts, because the hardware field is a signed 11-bit quantity and anything below is rejected. The instruction is to start at zero and test small changes under load, with the reason given plainly: values stable on one CPU can crash another CPU of the same model.
That last sentence is the honest summary of the whole feature. The tool cannot tell you whether a given offset is safe, because safe is a property of the individual chip rather than the model name.
There is also a hard limit the project states about itself: undervolting is disabled by firmware or microcode on many newer Intel systems, and `throttled` cannot bypass a locked voltage interface. On those machines the feature is simply unavailable, and no configuration will change that.
Five package formats, and the wheel is explicitly not the route for an end user
The release publishes five artefacts, and the table that lists them is more informative than the package names suggest. The Debian row is qualified: it applies to a Debian-family system that already has `python3-dbus-fast`, so the binding the daemon needs is expected to be present before the package installs. The Fedora and Alpine rows are not qualified. The wheel is a pure-Python `py3-none-any` artefact, and the source archive is offered to packagers. Downloads are verified against a `SHA256SUMS` file published with the release.
The install commands differ in what they do afterwards. On a running systemd host the Debian package enables and starts the service by itself. The Fedora route needs an explicit `systemctl enable --now throttled.service` after the install. The Alpine route uses OpenRC commands and requires `--allow-untrusted` on the add, because the upstream APK is not repository-signed.
The wheel is the odd one out and the README says so directly: it installs the `throttled` command only, and does not install the privileged service, the operating system dependencies or `/etc/throttled.conf`. End users are pointed at a native package or the source installer instead.
Distribution packages exist for Arch, Alpine, a Fedora Copr and Gentoo, and one sentence covers all of them: they are maintained independently and can lag behind the latest upstream release.
Three flat modules at the root, and two exact-pinned dependencies, one of which shadows the standard library
There is no importable package here. The implementation is three modules sitting at the repository root: `throttled.py`, `mmio.py` and `throttled_version.py`, declared in the packaging configuration as top-level modules rather than as a package. The console entry point is a module-level main function, so the command and the module share a name. `mmio.py` is the memory-mapped I/O layer, which is where the register writes live, and `version` is kept in its own file so that setuptools can read the version from an attribute without importing the daemon.
Installing the wheel therefore places a top-level module named `mmio` into site-packages, where it can collide with an unrelated package of the same name.
There are exactly two runtime dependencies and both are pinned to an exact patch version: `configparser==7.2.0` and `dbus-fast==5.0.22`. The same two lines appear in the requirements file, identically.
The first of those deserves a note. `configparser` on a package index is a backport of the module that Python ships in its standard library, and the project requires 3.10 or newer, where the standard library version already exists. Pinning a backport of a standard module to one exact release means the daemon's INI parsing comes from that package rather than from the interpreter, and any other tool in the same environment that expects the standard module gets the backport.
The rest of the tree supports the packaging story: a packaging configuration that produces the DEB, RPM and APK files, three service directories for the three init systems the README says it supports, an `etc/` directory holding the default configuration, an install script that creates an isolated environment under `/opt/throttled` and preserves an existing `/etc/throttled.conf` when reinstalling, and a documentation directory holding the community-reported hardware list. That list is where you should look before enabling the service, since the README is explicit that support depends on the CPU, firmware and kernel rather than on the laptop brand.
Editorial conclusion
throttled fits a laptop whose firmware repeatedly clamps power below what the hardware can sustain, on a machine you own and can reinstall, and where you have already confirmed the symptom with a read-only tool before changing anything. Three things to check first. Read the caution the project puts above everything else: it runs as root, it writes directly to CPU and chipset registers, and wrong values can make a system unstable or damage hardware, so the configuration has to be reviewed against your CPU and cooling. Treat the shipped numbers as a starting point rather than a recommendation, since the README says in as many words that they are project defaults and not recommendations for every system. And do not install the wheel for a machine you depend on: it ships the command without the privileged service, the operating system dependencies or the configuration file, so it is the packaging route for inspection rather than for use.
Frequently asked questions
what is throttled
A Linux daemon that prevents unwanted CPU throttling on some Intel-based systems. It periodically restores package power limits, PL1 and PL2, and the temperature target in MSR and MCHBAR registers when firmware or the embedded controller resets them, with separate AC and battery profiles, optional undervolting, IccMax overrides, experimental cTDP, HWP and BD PROCHOT controls, and live throttling diagnostics.
Can throttled damage my laptop?
The README's caution says it runs as root and writes directly to CPU and chipset registers, and that incorrect power, temperature, voltage or current values can make a system unstable or damage hardware. It tells you to review the configuration for your CPU and cooling system before enabling the service, and to check processor limits and cooling capacity before changing the shipped defaults.
How do I install throttled on Debian?
Take the DEB from the latest release and run `sudo apt install ./throttled_0.13_all.deb`. The release table qualifies that package as being for a Debian-family system with `python3-dbus-fast` already present. On a running systemd host the package enables and starts the service itself; the RPM route instead needs `sudo systemctl enable --now throttled.service` after the install.
Does throttled work on a new Intel laptop with locked undervolting?
Not for undervolting. The README states that undervolting is disabled by firmware or microcode on many newer Intel systems and that throttled cannot bypass a locked voltage interface. Where it is available, offsets are configured in the undervolting sections, only zero or negative values down to -1000 millivolts are accepted because the hardware field is a signed 11-bit quantity, and values that are stable on one CPU can crash another of the same model.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/erpalma-throttled)