Build1 distinct publisher3 min readPublished
An Odoo fiscal module caps its inline call to the Kenya Revenue Authority at four seconds, then doubles from 15 seconds for nine attempts. On a network where the endpoint often takes several seconds, that queue is the normal path.
The Engineer · Build desk

Compiled by The EngineerSomething wrong?How this is made
The writeup contains two timeouts, set at very different limits. The anti-pattern version calls requests.post with timeout=30 inside action_post, holding an Odoo WSGI worker for up to half a minute per posted invoice, and losing the invoice rollback if the Kenya Revenue Authority drops the connection [6]. The shipped module caps the inline attempt at 4 seconds [8]. That is 4/30 of the worker hold, near 13 percent [20], and it is the only piece of the fiscalisation path you can size a worker pool against.
The same post says KRA endpoints often take several seconds to answer during peak filing deadlines [7]. Set the inline budget below the observed response time and the retry queue stops being an exception handler. It carries ordinary traffic in exactly the week volumes peak. The cron interval, not the KRA endpoint, then decides how soon a customer's receipt gets its control code.
The ladder is arithmetic you can run. Each failure sets the next wait to (2 ** retry_count) * 15 seconds plus 1 to 10 seconds of jitter [14], and a retry_count above 8 marks the row permanently failed [13]. That allows nine cron attempts [18]. Eight waits at 15 times 2, 4, 8, 16, 32, 64, 128 and 256 sum to 7,650 seconds, or 2 hours 7 minutes 30 seconds, plus 8 to 80 seconds of jitter [19]. Treat it as a floor. The clock only advances when the cron fires, and the writeup does not state the sweep frequency [21].
The indexing on the queue model reflects careful work. state and next_retry_time both carry index=True, and the sweep domain queries exactly those two columns with limit=50 [11][12]. Two small things read differently. move_id is declared ondelete="cascade" [11], so the queue is coupled to the document lifecycle rather than standing as an independent log of transmission attempts. And the prose says a failed call marks the record pending_retry [10], which is not one of the four values in the Selection [11]. Naming drift in a blog post is cheap; naming drift between the narrative and the state machine is where an ops runbook goes wrong.
The important gap here is a legal one. The post opens by stating that a POS knocked offline by a fiber cut cannot lawfully issue receipts [3], and it ends the eTIMS section saying the QR code and Control Unit ID render on QWeb PDFs and OWL thermal receipts [15]. What a thermal printer emits while the queue row is still pending is not shown [22]. Deferred signing is the right shape for the worker pool. Whether it is the right shape for a KRA audit depends on that unprinted receipt.
On the payment side, the writeup runs out. It describes STK Push from the till and unsolicited C2B payments to a Paybill or Till number [16], in a market it puts at over 80 percent of commercial transactions settling through M-Pesa [2], and confirms Safaricom sends validation and confirmation callbacks over HTTPS [17]. The text then breaks off mid-sentence on the network hops between Safaricom and the customer instance [17]. Reconciliation of duplicate or late confirmations, the half that decides whether the accounting team keeps typing, is not in the published portion.
Ranked by verification strength, evidence, and original report placement.
The writeup states Safaricom sends validation and confirmation callbacks via HTTPS, and the published text then breaks off mid-sentence while describing network hops between Safaricom and the client instance.
The Kenya Revenue Authority requires every business invoice to carry a digital fiscal signature and a verifiable QR code via eTIMS.
The writeup states that if a retail POS goes offline when the fiber cuts, you cannot legally issue receipts.
The authors built and published three production modules on the official Odoo App Store, supporting Odoo 17.0, 18.0 and 19.0 across both Community and Enterprise editions.
The standard KRA eTIMS Online Sales Control Unit flow requires sending invoice line items, tax classification codes and buyer PINs to KRA over HTTPS; KRA returns control unit internal data, an invoice sequence number and a verification URL encoded as a QR code.
The writeup names an anti-pattern: a synchronous requests.post with timeout=30 inside AccountMove.action_post, which ties up the HTTP worker if KRA takes 15 seconds and breaks the entire invoice rollback if KRA drops.
Distinct publishers with included, body-backed reporting in this cluster.
1 article · September 5, 2026
Follow any of these and your For You feed starts watching them — no settings page required.
build
Strapi will send that webhook twice, so your receiver owns the idempotency key1 distinct publisher
build
A self-healing Odoo layer scored 83.3 percent, and the 16.7 percent is the useful part1 distinct publisher
Evidence-backed comparisons of source perspectives and observed adoption signals. Read the methodology
Which Builder, Operator, and Investor concerns the observed source mix emphasized—not a truth score.
Evidence, demonstrated adoption, hype gap, incentives, and confidence are assessed independently, each on its own current evidence. How these are measured.
Code verified, claims unverified
The mechanism can be verified by reading the post: field definitions, the search domain, the cap at retry_count > 8 and the backoff expression are all printed, which is why the two-hour window holds up as arithmetic. The claims that make the design necessary are a different matter. Both the 80 percent M-Pesa settlement share and 'KRA endpoints often take several seconds' come from the team selling the fix, with no sample or citation, and the writeup stops mid-sentence before the M-Pesa reconciliation logic is shown.
App Store listings exist, no users confirmed
Publication on the Odoo App Store across three Odoo versions is the entire uptake record, and it is the vendor's own statement rather than a listing anyone has checked. There are no install counts and no named deployment, and nothing in the reporting indicates a Kenyan taxpayer has filed an invoice through this queue.
Compliance claimed on the happy path
The eTIMS section closes by saying the design satisfies statutory requirements without stalling billing, and that is accurate for the four-second inline case. By the authors' own account of KRA response times, the retry ladder is where ordinary invoices land, and its slowest rung alone is over an hour. The unstated cron interval and the silence on what a thermal receipt shows while a row is pending are exactly the two details that would tell a reader how often compliance is deferred.
Vendor build log for its own listings
This is the author of jengastack_etims and jengastack_mpesa describing why you should install them, published alongside a note that three modules are live on the Odoo App Store. The dismissal of other M-Pesa plugins as treating payments 'as an afterthought' is competitive positioning inside a technical piece, and the two market facts that establish demand are the two nothing else in this coverage attests.
Solid on the code, weak on the surrounding claims
Anything about the retry ladder can be held to the published source and checked, which is why the timing claims stand. Everything around it depends on a single self-interested account that no other publisher has touched, and the piece is incomplete where the M-Pesa path would have been most testable.