<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Tecnick.com LTD on Tecnick.com</title><link>https://tecnick.com/</link><description>Recent content in Tecnick.com LTD on Tecnick.com</description><generator>Hugo</generator><language>en-gb</language><lastBuildDate>Tue, 08 Sep 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://tecnick.com/index.xml" rel="self" type="application/rss+xml"/><item><title>Articles</title><link>https://tecnick.com/articles/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://tecnick.com/articles/</guid><description/></item><item><title>Search</title><link>https://tecnick.com/search/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://tecnick.com/search/</guid><description/></item><item><title>Software</title><link>https://tecnick.com/software/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://tecnick.com/software/</guid><description>&lt;p&gt;Tecnick.com is strongly engaged in the development and maintenance of &lt;a href="https://opensource.org/"&gt;Open Source&lt;/a&gt;&#10; projects. Over the years we have contributed to several third-party Open Source projects and published many original ones. The actively maintained projects are listed first, followed by legacy and archived projects that are kept online for reference.&lt;/p&gt;&#10;&lt;h2 id="actively-maintained"&gt;Actively Maintained&lt;/h2&gt;&#10;&lt;h3 id="go"&gt;Go&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;a href="https://github.com/tecnickcom/nurago"&gt;&lt;strong&gt;nurago&lt;/strong&gt;&lt;/a&gt;&#10;&lt;br&gt;&#10;Collection of modular and reusable Go (golang) packages for building services and infrastructure code, including a web-service project builder.&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://github.com/tecnickcom/rpistat"&gt;&lt;strong&gt;rpistat&lt;/strong&gt;&lt;/a&gt;&#10;&lt;br&gt;&#10;Web-Service to collect system usage statistics.&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://github.com/tecnickcom/rndpwd"&gt;&lt;strong&gt;rndpwd&lt;/strong&gt;&lt;/a&gt;&#10;&lt;br&gt;&#10;Web-Service Random Password Generator written in Go (example project).&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://github.com/tecnickcom/statsd"&gt;&lt;strong&gt;statsd&lt;/strong&gt;&lt;/a&gt;&#10;&lt;br&gt;&#10;Simple and efficient StatsD client, supporting counter, gauge, timing and set metrics with InfluxDB and Datadog tags.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="c-and-multi-language-libraries"&gt;C and Multi-language Libraries&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;a href="https://github.com/tecnickcom/variantkey"&gt;&lt;strong&gt;variantkey&lt;/strong&gt;&lt;/a&gt;&#10;&lt;br&gt;&#10;Reversible numerical encoding for human genetic variants and regions. Available for C, Go, Python, Javascript and R.&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://github.com/tecnickcom/farmhash64"&gt;&lt;strong&gt;farmhash64&lt;/strong&gt;&lt;/a&gt;&#10;&lt;br&gt;&#10;Portable multi-language implementation of the FarmHash64 and FarmHash32 non-cryptographic fingerprint hash functions. Available for C, CGO, Go, Java, Javascript, PHP, Python, R, Rust and Zig.&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://github.com/tecnickcom/binsearch"&gt;&lt;strong&gt;binsearch&lt;/strong&gt;&lt;/a&gt;&#10;&lt;br&gt;&#10;Fast binary search of unsigned integers in memory-mapped columnar binary files, including the Apache Arrow, Feather and BINSRC1 formats. Available for C, Go and Python.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="php-and-web-applications"&gt;PHP and Web Applications&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;a href="https://tcexam.org"&gt;&lt;strong&gt;TCExam&lt;/strong&gt;&lt;/a&gt;&#10;&lt;br&gt;&#10;Computer-Based Assessment (CBA) system for universities, schools and companies, that enables educators and trainers to author, schedule, deliver and report on surveys, quizzes, tests and exams.&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://github.com/tecnickcom/web-cctray"&gt;&lt;strong&gt;web-cctray&lt;/strong&gt;&lt;/a&gt;&#10;&lt;br&gt;&#10;Web-based dashboard for CI/CD cctray.xml files.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="php-libraries"&gt;PHP Libraries&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;a href="https://tcpdf.org"&gt;&lt;strong&gt;tc-lib-pdf&lt;/strong&gt;&lt;/a&gt;&#10;&lt;br&gt;&#10;PHP PDF library (TCPDF), to generate PDF documents on-the-fly without requiring external extensions.&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://github.com/tecnickcom/tc-lib-barcode"&gt;&lt;strong&gt;tc-lib-barcode&lt;/strong&gt;&lt;/a&gt;&#10;&lt;br&gt;&#10;PHP library to generate 70+ linear, 2D and postal barcodes as SVG, PNG, HTML or text.&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://github.com/tecnickcom/tc-lib-pdf-font"&gt;&lt;strong&gt;tc-lib-pdf-font&lt;/strong&gt;&lt;/a&gt;&#10;&lt;br&gt;&#10;PHP library containing PDF font methods and utilities.&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://github.com/tecnickcom/tc-lib-pdf-page"&gt;&lt;strong&gt;tc-lib-pdf-page&lt;/strong&gt;&lt;/a&gt;&#10;&lt;br&gt;&#10;PHP library containing PDF page formats and definitions.&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://github.com/tecnickcom/tc-lib-pdf-image"&gt;&lt;strong&gt;tc-lib-pdf-image&lt;/strong&gt;&lt;/a&gt;&#10;&lt;br&gt;&#10;PHP library containing PDF Image methods.&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://github.com/tecnickcom/tc-lib-pdf-graph"&gt;&lt;strong&gt;tc-lib-pdf-graph&lt;/strong&gt;&lt;/a&gt;&#10;&lt;br&gt;&#10;PHP library containing PDF graphic and geometric methods.&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://github.com/tecnickcom/tc-lib-pdf-sign"&gt;&lt;strong&gt;tc-lib-pdf-sign&lt;/strong&gt;&lt;/a&gt;&#10;&lt;br&gt;&#10;PHP library containing digital signature primitives for PDF documents (PKCS#7, CAdES, PAdES).&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://github.com/tecnickcom/tc-lib-pdf-parser"&gt;&lt;strong&gt;tc-lib-pdf-parser&lt;/strong&gt;&lt;/a&gt;&#10;&lt;br&gt;&#10;PHP library to parse PDF documents.&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://github.com/tecnickcom/tc-lib-pdf-encrypt"&gt;&lt;strong&gt;tc-lib-pdf-encrypt&lt;/strong&gt;&lt;/a&gt;&#10;&lt;br&gt;&#10;PHP library to encrypt data for PDF documents.&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://github.com/tecnickcom/tc-lib-pdf-filter"&gt;&lt;strong&gt;tc-lib-pdf-filter&lt;/strong&gt;&lt;/a&gt;&#10;&lt;br&gt;&#10;PHP library to decode PDF compression and encryption filters.&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://github.com/tecnickcom/tc-lib-unicode"&gt;&lt;strong&gt;tc-lib-unicode&lt;/strong&gt;&lt;/a&gt;&#10;&lt;br&gt;&#10;PHP library containing Unicode methods, including UTF-8 conversions, the Unicode Bidirectional Algorithm (UAX #9) and script-specific character substitutions.&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://github.com/tecnickcom/tc-lib-unicode-data"&gt;&lt;strong&gt;tc-lib-unicode-data&lt;/strong&gt;&lt;/a&gt;&#10;&lt;br&gt;&#10;PHP library containing UTF-8 font definitions.&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://github.com/tecnickcom/tc-lib-file"&gt;&lt;strong&gt;tc-lib-file&lt;/strong&gt;&lt;/a&gt;&#10;&lt;br&gt;&#10;PHP library to read byte-level data from files.&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://github.com/tecnickcom/tc-lib-color"&gt;&lt;strong&gt;tc-lib-color&lt;/strong&gt;&lt;/a&gt;&#10;&lt;br&gt;&#10;PHP library to parse, convert and format the color representations used in web and PDF output.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="font-assets"&gt;Font Assets&lt;/h3&gt;&#10;&lt;p&gt;Data-only packages that provide the font resources used by the PDF toolchain.&lt;/p&gt;</description></item><item><title>Websites</title><link>https://tecnick.com/websites/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://tecnick.com/websites/</guid><description>&lt;p&gt;Tecnick.com owns and manages a portfolio of technology-focused websites that provide open resources, practical tools, and technical documentation for developers, engineers, students, and digital makers.&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;a href="https://technick.net"&gt;&lt;strong&gt;technick.net&lt;/strong&gt;&lt;/a&gt;&#10; - Guides and online tools for electronics, hardware and software&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://allpinouts.org"&gt;&lt;strong&gt;allpinouts.org&lt;/strong&gt;&lt;/a&gt;&#10; - Archive of cable and connector pinouts&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://circuitsarchive.org"&gt;&lt;strong&gt;circuitsarchive.org&lt;/strong&gt;&lt;/a&gt;&#10; - Archive of electronic circuit schematics and projects&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://nurago.org"&gt;&lt;strong&gt;nurago.org&lt;/strong&gt;&lt;/a&gt;&#10; - Open Source collection of modular Go packages for backend services&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://tcpdf.org"&gt;&lt;strong&gt;tcpdf.org&lt;/strong&gt;&lt;/a&gt;&#10; - Open Source PHP library to generate PDF documents (TCPDF and tc-lib-pdf)&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://tcexam.org"&gt;&lt;strong&gt;tcexam.org&lt;/strong&gt;&lt;/a&gt;&#10; - Open Source Computer-Based Assessment (CBA) system&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://testimages.org"&gt;&lt;strong&gt;testimages.org&lt;/strong&gt;&lt;/a&gt;&#10; - Archive of free test images for research and display testing&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://atletix.net"&gt;&lt;strong&gt;atletix.net&lt;/strong&gt;&lt;/a&gt;&#10; - [IT] Guide, strumenti e calcolatori per l&amp;rsquo;attività motoria e l&amp;rsquo;atletica leggera&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://appunti.asuni.xyz"&gt;&lt;strong&gt;appunti.asuni.xyz&lt;/strong&gt;&lt;/a&gt;&#10; - [IT] Appunti universitari di Nicola Asuni&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://nicola.asuni.xyz"&gt;&lt;strong&gt;nicola.asuni.xyz&lt;/strong&gt;&lt;/a&gt;&#10; - Nicola Asuni&amp;rsquo;s personal website and professional profile&lt;/li&gt;&#10;&lt;/ul&gt;</description></item><item><title>Legal</title><link>https://tecnick.com/legal/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://tecnick.com/legal/</guid><description>&lt;h2&gt;Disclaimer&lt;/h2&gt;&#10;&#10;&lt;p&gt;&lt;strong&gt;Please be aware that any information you find on this website may be inaccurate, misleading or out of date.&lt;/strong&gt;&lt;/p&gt;&#10;&#10;&lt;p&gt;Some information on Tecnick.com may create a risk for readers who choose to apply or use it in their own activities, or who promote it for use by third parties. None of the authors or contributors connected with Tecnick.com can be held responsible, in any way whatsoever, for your use of the information contained in or linked from these pages.&lt;/p&gt;</description></item><item><title>TCPDF: 25 Years of Generating PDFs in PHP</title><link>https://tecnick.com/articles/tcpdf/</link><pubDate>Sun, 28 Jun 2026 00:00:00 +0000</pubDate><guid>https://tecnick.com/articles/tcpdf/</guid><description>&lt;hr&gt;&#10;&lt;img src="https://tecnick.com/img/tc-lib-pdf_journey_640x272.png" alt="tecnickcom/tc-lib-pdf" width="640" height="300" /&gt;&#10;&lt;p&gt;Many PHP applications end up needing to produce a PDF. An invoice, a shipping label, a course certificate, a signed contract, a monthly report. It is one of those unglamorous requirements that turns up on project after project, and it is rarely as simple as it first sounds.&lt;/p&gt;&#10;&lt;p&gt;I know, because I have been writing the code that does it for twenty-five years.&lt;/p&gt;&#10;&lt;p&gt;If you have generated a PDF from PHP at any point in the last two decades, there is a good chance some of my code was involved. TCPDF, the library I started in 2002, has been installed more than 109 million times through Composer alone, and it is a dependency of a long list of applications you already know. I have even found documents generated by TCPDF sitting on NASA&amp;rsquo;s own data-centre websites. More on that below.&lt;/p&gt;</description></item><item><title>Stop Rewriting Go Service Boilerplate: Ship Production Go APIs Faster with nurago</title><link>https://tecnick.com/articles/nurago/</link><pubDate>Sun, 29 Mar 2026 00:00:00 +0000</pubDate><guid>https://tecnick.com/articles/nurago/</guid><description>&lt;hr&gt;&#10;&lt;img src="https://tecnick.com/img/nurago_pipeline_640x300.png" alt="tecnickcom/nurago pipeline" width="640" height="300" /&gt;&#10;&lt;p&gt;Every backend team says the same thing when starting a new service:&lt;/p&gt;&#10;&lt;p&gt;&amp;ldquo;This one will be lean.&amp;rdquo;&lt;/p&gt;&#10;&lt;p&gt;Then the infrastructure checklist arrives.&lt;/p&gt;&#10;&lt;p&gt;Configuration loading. Structured logging. Metrics. Retries. Health checks. Graceful shutdown. Validation. Cache layers. Cloud clients. Test utilities.&lt;/p&gt;&#10;&lt;p&gt;None of it is core business logic. All of it is essential in production.&lt;/p&gt;&#10;&lt;p&gt;After watching that pattern repeat across teams and projects, I consolidated the building blocks I kept rewriting into one open-source project: &lt;a href="https://github.com/tecnickcom/nurago"&gt;nurago&lt;/a&gt;&#10;.&lt;/p&gt;</description></item><item><title>Software Quality Is a System, Not an Act: Inside the Quality Pipeline of nurago</title><link>https://tecnick.com/articles/software-quality/</link><pubDate>Sat, 11 Jul 2026 00:00:00 +0000</pubDate><guid>https://tecnick.com/articles/software-quality/</guid><description>&lt;hr&gt;&#10;&lt;img src="https://tecnick.com/img/quality_pipeline_640x300.png" alt="tecnickcom/nurago quality pipeline" width="640" height="300" /&gt;&#10;&lt;p&gt;Saying a project cares about software quality is easy. Pointing at the exact mechanisms that produce it is harder.&lt;/p&gt;&#10;&lt;p&gt;Quality is not a final inspection step, and it is not a property you can bolt on before a release. It is the cumulative result of dozens of small, boring, automated decisions that either happen on every commit or do not happen at all.&lt;/p&gt;&#10;&lt;p&gt;That is what the title of this article means. An act is something a person performs at a moment in time: a QA phase before the release, a yearly security audit, a reviewer being especially careful on a good day. Acts depend on memory, time, and goodwill, and they are the first casualty of deadline pressure; their results start decaying the moment they end. A system is a standing structure that produces quality as its normal output: automated, continuous, redundant, and measured, regardless of who is busy that week. W. Edwards Deming made the underlying point about manufacturing decades ago: you cannot inspect quality into a product; you have to build it into the process that makes it.&lt;/p&gt;</description></item><item><title>Redacting Secrets from Go Logs on a Performance Budget</title><link>https://tecnick.com/articles/nurago-redact/</link><pubDate>Sat, 18 Jul 2026 00:00:00 +0000</pubDate><guid>https://tecnick.com/articles/nurago-redact/</guid><description>&lt;hr&gt;&#10;&lt;p&gt;Services leak secrets into their own logs all the time. Someone dumps an inbound HTTP request to debug a flaky integration and the &lt;code&gt;Authorization&lt;/code&gt; header goes straight to disk. A JSON body with a &lt;code&gt;password&lt;/code&gt; field lands in an error log. A connection string with the database password ends up in a stack trace. Nobody did anything reckless. They logged what they needed to see when something broke, and the credentials came along for the ride.&lt;/p&gt;</description></item><item><title>Packing an Entire Country Record into a Single uint64</title><link>https://tecnick.com/articles/nurago-countrycode/</link><pubDate>Sat, 18 Jul 2026 00:00:00 +0000</pubDate><guid>https://tecnick.com/articles/nurago-countrycode/</guid><description>&lt;hr&gt;&#10;&lt;p&gt;Country metadata is one of those unglamorous needs that turns up in most backends. Translate &lt;code&gt;US&lt;/code&gt; to &lt;code&gt;USA&lt;/code&gt; to &lt;code&gt;840&lt;/code&gt;. Find which region a country belongs to. Validate a country top-level domain (TLD). The usual answer is a pile of maps, one per lookup direction, each holding strings, and it works well enough that nobody looks twice at it.&lt;/p&gt;&#10;&lt;p&gt;The &lt;a href="https://github.com/tecnickcom/nurago/tree/main/pkg/countrycode"&gt;&lt;code&gt;countrycode&lt;/code&gt;&lt;/a&gt;&#10; package in &lt;a href="https://github.com/tecnickcom/nurago"&gt;nurago&lt;/a&gt;&#10; does something else. Internally, an entire International Organization for Standardization (ISO) 3166 country record is encoded into a single 64-bit integer, and every lookup is a handful of shifts away from that one number.&lt;/p&gt;</description></item><item><title>The Life of a Password: Argon2id in Production with nurago</title><link>https://tecnick.com/articles/nurago-passwordhash/</link><pubDate>Sat, 18 Jul 2026 00:00:00 +0000</pubDate><guid>https://tecnick.com/articles/nurago-passwordhash/</guid><description>&lt;hr&gt;&#10;&lt;p&gt;Password storage is one of the more consequential things a service does, and it has a long record of being botched. General-purpose hashes like MD5 and SHA-1 are the classic mistake: fast, and trivially parallelised on a GPU, which is precisely backwards.&lt;/p&gt;&#10;&lt;p&gt;What the job calls for is a hash that is deliberately slow and &lt;em&gt;memory-hard&lt;/em&gt;, needing a large tunable amount of RAM per guess. That is what neutralises the massively parallel GPU and Application-Specific Integrated Circuit (ASIC) rigs used to crack leaked password databases. Bcrypt is slow but uses a fixed, tiny amount of memory, so those rigs still scale against it. Password-Based Key Derivation Function 2 (PBKDF2), the usual choice when Federal Information Processing Standards (FIPS) compliance is required, iterates a cheap hash and is not memory-hard at all. Scrypt is memory-hard, but ties memory and CPU cost to a single knob. Argon2, the Password Hashing Competition (PHC) winner standardised as RFC 9106, lets you dial time, memory, and parallelism independently, and its &lt;code&gt;id&lt;/code&gt; variant adds resistance to side-channel attacks. Hence its place at the top of the Open Worldwide Application Security Project (OWASP) Password Storage Cheat Sheet.&lt;/p&gt;</description></item><item><title>The Classic JWT Attacks, Addressed by Construction in Go</title><link>https://tecnick.com/articles/nurago-jwt/</link><pubDate>Sat, 18 Jul 2026 00:00:00 +0000</pubDate><guid>https://tecnick.com/articles/nurago-jwt/</guid><description>&lt;hr&gt;&#10;&lt;p&gt;JSON Web Tokens (JWTs) have a reputation for being dangerous, and the reputation is earned. The danger is almost never in the cryptography; it is in the flexibility of the format. A token header announces how it was signed, and a naive verifier believes the announcement. Many published JWT exploits are variations on that single act of misplaced trust.&lt;/p&gt;&#10;&lt;p&gt;The &lt;a href="https://github.com/tecnickcom/nurago/tree/main/pkg/jwt"&gt;&lt;code&gt;jwt&lt;/code&gt;&lt;/a&gt;&#10; package in &lt;a href="https://github.com/tecnickcom/nurago"&gt;nurago&lt;/a&gt;&#10; takes a stricter stance. Each of the classic attacks is closed by how the package is built, rather than by a runtime check someone could forget to call or misconfigure away. Here is the list, one attack at a time.&lt;/p&gt;</description></item><item><title>Checking Passwords Against Have I Been Pwned Without Leaking Them</title><link>https://tecnick.com/articles/nurago-passwordpwned/</link><pubDate>Sat, 18 Jul 2026 00:00:00 +0000</pubDate><guid>https://tecnick.com/articles/nurago-passwordpwned/</guid><description>&lt;hr&gt;&#10;&lt;p&gt;Rejecting passwords that have appeared in known data breaches is a high-value check for a registration flow, and the best-known source is Troy Hunt&amp;rsquo;s Have I Been Pwned (HIBP) Pwned Passwords database. The obvious objection: sending a user&amp;rsquo;s password, or even its full hash, to a third-party service to ask &amp;ldquo;have you seen this?&amp;rdquo; would itself be a security incident.&lt;/p&gt;&#10;&lt;p&gt;The &lt;a href="https://github.com/tecnickcom/nurago/tree/main/pkg/passwordpwned"&gt;&lt;code&gt;passwordpwned&lt;/code&gt;&lt;/a&gt;&#10; package in &lt;a href="https://github.com/tecnickcom/nurago"&gt;nurago&lt;/a&gt;&#10; implements the check in a way that answers that objection. Following the exchange as a network observer would is the quickest way to see how: what leaves the machine, what comes back, and what happens when the answer cannot be trusted.&lt;/p&gt;</description></item><item><title>From singleflight to a Production Cache: a Gap Analysis</title><link>https://tecnick.com/articles/nurago-sfcache/</link><pubDate>Sat, 18 Jul 2026 00:00:00 +0000</pubDate><guid>https://tecnick.com/articles/nurago-sfcache/</guid><description>&lt;hr&gt;&#10;&lt;p&gt;Some lookups are too expensive to run on every request: a Domain Name System (DNS) resolution, a secret from a vault, slow remote metadata. Caching them is the natural move, and it brings a well-known hazard: when a hot value expires, a crowd of goroutines can rush the upstream at once, the cache stampede. In Go, the usual remedy is &lt;code&gt;golang.org/x/sync/singleflight&lt;/code&gt;, which lets one goroutine do the work while the other forty-nine wait for its result.&lt;/p&gt;</description></item><item><title>Deriving a Fast Fixed-Width Hex Encoder in Go</title><link>https://tecnick.com/articles/nurago-uhex/</link><pubDate>Sat, 18 Jul 2026 00:00:00 +0000</pubDate><guid>https://tecnick.com/articles/nurago-uhex/</guid><description>&lt;hr&gt;&#10;&lt;p&gt;Hexadecimal encoding is a solved problem. The standard library has &lt;code&gt;encoding/hex&lt;/code&gt;, and if you just want a string there is always &lt;code&gt;fmt.Sprintf(&amp;quot;%x&amp;quot;, v)&lt;/code&gt;. So why does &lt;a href="https://github.com/tecnickcom/nurago"&gt;nurago&lt;/a&gt;&#10; ship a dedicated &lt;a href="https://github.com/tecnickcom/nurago/tree/main/pkg/uhex"&gt;&lt;code&gt;uhex&lt;/code&gt;&lt;/a&gt;&#10; package?&lt;/p&gt;&#10;&lt;p&gt;Because the places where hex encoding runs hottest, trace IDs, hashes, log fields, protocol framing, share a property the general tools cannot exploit: the width is fixed and known at compile time. Derive &lt;code&gt;uhex&lt;/code&gt; from the standard library by removing one cost at a time, and you can see exactly what that constraint buys.&lt;/p&gt;</description></item><item><title>Exponential Backoff with Jitter in Go, Without the Overflow Footgun</title><link>https://tecnick.com/articles/nurago-backoff/</link><pubDate>Sat, 18 Jul 2026 00:00:00 +0000</pubDate><guid>https://tecnick.com/articles/nurago-backoff/</guid><description>&lt;hr&gt;&#10;&lt;p&gt;Exponential backoff is the usual first response when a downstream call starts failing: wait a bit, then wait longer, then longer still. It looks trivial. It hides two real bugs.&lt;/p&gt;&#10;&lt;p&gt;The first is the &lt;em&gt;thundering herd&lt;/em&gt;. Without jitter, a fleet of clients that all failed at the same instant will all retry at the same instant, hammering the recovering service in synchronised waves.&lt;/p&gt;&#10;&lt;p&gt;The second is that the delay arithmetic can overflow. Signed integer arithmetic in Go wraps around, so a &lt;code&gt;time.Duration&lt;/code&gt; that grows past &lt;code&gt;math.MaxInt64&lt;/code&gt; nanoseconds does not saturate. It comes back &lt;em&gt;negative&lt;/em&gt;. The timing is what makes it nasty: delays only get that large after many consecutive failures, so the overflow fires in the middle of your worst outage, at the exact moment backoff was supposed to be doing its job.&lt;/p&gt;</description></item><item><title>Random IDs in Go, Trap by Trap: UUIDv7 and Unbiased Random Strings</title><link>https://tecnick.com/articles/nurago-random/</link><pubDate>Sat, 18 Jul 2026 00:00:00 +0000</pubDate><guid>https://tecnick.com/articles/nurago-random/</guid><description>&lt;hr&gt;&#10;&lt;p&gt;Generating random identifiers looks trivial and hides several traps. Reach for &lt;code&gt;math/rand&lt;/code&gt; out of habit and your &amp;ldquo;secure&amp;rdquo; token is predictable. Map random bytes onto an alphabet with a naive &lt;code&gt;% len&lt;/code&gt; and you skew the distribution. Accept whatever a custom entropy reader hands you and you can end up with truncated randomness, or a call that never returns.&lt;/p&gt;&#10;&lt;p&gt;The &lt;a href="https://github.com/tecnickcom/nurago/tree/main/pkg/random"&gt;&lt;code&gt;random&lt;/code&gt;&lt;/a&gt;&#10; package in &lt;a href="https://github.com/tecnickcom/nurago"&gt;nurago&lt;/a&gt;&#10; centralises these patterns behind one small API. &lt;code&gt;New(nil)&lt;/code&gt; draws from &lt;code&gt;crypto/rand.Reader&lt;/code&gt;, the right default for anything security-sensitive, and a custom &lt;code&gt;io.Reader&lt;/code&gt; can be supplied for testing or specialised entropy sources:&lt;/p&gt;</description></item><item><title>Filtering Untrusted Client Queries in Go: Threat Model First</title><link>https://tecnick.com/articles/nurago-filter/</link><pubDate>Sat, 18 Jul 2026 00:00:00 +0000</pubDate><guid>https://tecnick.com/articles/nurago-filter/</guid><description>&lt;hr&gt;&#10;&lt;p&gt;A &lt;code&gt;filter=&lt;/code&gt; query parameter is a common way to let clients narrow down a list endpoint. The client asks for &amp;ldquo;users named Doe, at most 42 years old, in England or France&amp;rdquo;, and the server turns that into a predicate over an in-memory slice. It looks like a small convenience. It is also a little expression language exposed to the open internet, which makes the hostile client the right place to start designing from. The &lt;a href="https://github.com/tecnickcom/nurago/tree/main/pkg/filter"&gt;&lt;code&gt;filter&lt;/code&gt;&lt;/a&gt;&#10; package in &lt;a href="https://github.com/tecnickcom/nurago"&gt;nurago&lt;/a&gt;&#10; is built that way, so the threat model comes first here and the machinery second.&lt;/p&gt;</description></item><item><title>A Longest-Prefix Trie for Numeric Keys, in Six Design Questions</title><link>https://tecnick.com/articles/nurago-numtrie/</link><pubDate>Sat, 18 Jul 2026 00:00:00 +0000</pubDate><guid>https://tecnick.com/articles/nurago-numtrie/</guid><description>&lt;hr&gt;&#10;&lt;p&gt;Some lookups are not &amp;ldquo;does this key exist&amp;rdquo; but &amp;ldquo;what is the most specific rule that applies to this key&amp;rdquo;. Telephone routing is the canonical example: a dialled number matches the longest stored prefix, so &lt;code&gt;+1 212 555 0100&lt;/code&gt; should resolve to a New York rule (&lt;code&gt;1212&lt;/code&gt;) if one exists, and fall back to a broader North American rule (&lt;code&gt;1&lt;/code&gt;) if it does not. A hash map answers only exact-key questions, so longest-prefix matching would need a separate probe for every shrinking prefix; a linear scan over a sorted list degrades as the table grows. The &lt;a href="https://github.com/tecnickcom/nurago/tree/main/pkg/numtrie"&gt;&lt;code&gt;numtrie&lt;/code&gt;&lt;/a&gt;&#10; package in &lt;a href="https://github.com/tecnickcom/nurago"&gt;nurago&lt;/a&gt;&#10; is a small generic trie built for exactly this question:&lt;/p&gt;</description></item><item><title>A Distributed Lock in Go and MySQL, and Every Way the Session Can Betray You</title><link>https://tecnick.com/articles/nurago-mysqllock/</link><pubDate>Sat, 18 Jul 2026 00:00:00 +0000</pubDate><guid>https://tecnick.com/articles/nurago-mysqllock/</guid><description>&lt;hr&gt;&#10;&lt;p&gt;Some work must happen at most once across an entire fleet: a nightly reconciliation, an idempotent migration, a cache rebuild. When several instances of a service could each try to run it, you need a lock that spans processes, and an in-memory mutex does not.&lt;/p&gt;&#10;&lt;p&gt;If MySQL is already in the stack, its built-in named locks are the tempting answer. &lt;code&gt;GET_LOCK('key', timeout)&lt;/code&gt; grants a server-wide lock, &lt;code&gt;RELEASE_LOCK('key')&lt;/code&gt; frees it, and you have avoided standing up a separate coordination service. The &lt;a href="https://github.com/tecnickcom/nurago/tree/main/pkg/mysqllock"&gt;&lt;code&gt;mysqllock&lt;/code&gt;&lt;/a&gt;&#10; package in &lt;a href="https://github.com/tecnickcom/nurago"&gt;nurago&lt;/a&gt;&#10; is under six hundred lines built on that primitive.&lt;/p&gt;</description></item><item><title>A DNS-Caching Dialer for http.Transport in Go</title><link>https://tecnick.com/articles/nurago-dnscache/</link><pubDate>Sat, 18 Jul 2026 00:00:00 +0000</pubDate><guid>https://tecnick.com/articles/nurago-dnscache/</guid><description>&lt;hr&gt;&#10;&lt;p&gt;Go&amp;rsquo;s standard &lt;code&gt;http.Transport&lt;/code&gt; resolves the destination host on every new connection and does not cache the result. For a client that talks to the same handful of hosts thousands of times a minute, that is a steady drip of Domain Name System (DNS) queries, each adding latency to connection setup and load on the resolver. The &lt;a href="https://github.com/tecnickcom/nurago/tree/main/pkg/dnscache"&gt;&lt;code&gt;dnscache&lt;/code&gt;&lt;/a&gt;&#10; package in &lt;a href="https://github.com/tecnickcom/nurago"&gt;nurago&lt;/a&gt;&#10; sits in that gap: a bounded, concurrency-safe DNS cache with a &lt;code&gt;DialContext&lt;/code&gt; you can drop straight into a transport.&lt;/p&gt;</description></item><item><title>A Production slog.Handler on Top of zerolog</title><link>https://tecnick.com/articles/nurago-logsrv/</link><pubDate>Sat, 18 Jul 2026 00:00:00 +0000</pubDate><guid>https://tecnick.com/articles/nurago-logsrv/</guid><description>&lt;hr&gt;&#10;&lt;p&gt;Go&amp;rsquo;s &lt;code&gt;log/slog&lt;/code&gt; gave the ecosystem a standard structured-logging interface, which is what you want to code against: your libraries speak &lt;code&gt;slog&lt;/code&gt; and stay portable. Teams that care about logging overhead often reach for &lt;a href="https://github.com/rs/zerolog"&gt;zerolog&lt;/a&gt;&#10;, whose reputation is allocation-free structured output.&lt;/p&gt;&#10;&lt;p&gt;The &lt;a href="https://github.com/tecnickcom/nurago/tree/main/pkg/logsrv"&gt;&lt;code&gt;logsrv&lt;/code&gt;&lt;/a&gt;&#10; package in &lt;a href="https://github.com/tecnickcom/nurago"&gt;nurago&lt;/a&gt;&#10; takes both. It implements a native &lt;code&gt;slog.Handler&lt;/code&gt; that writes each record&amp;rsquo;s attributes directly onto zerolog events. The work is all in the disagreements between the two APIs: what a level is, where attributes may nest, who owns rendering decisions, and who reports errors. Every heading below names one of those mismatches and answers it in three parts: what the &lt;code&gt;slog&lt;/code&gt; contract requires, how a naive bridge gets it wrong, and what this handler does instead.&lt;/p&gt;</description></item><item><title>Observing Outbound HTTP in Go Without Disturbing It</title><link>https://tecnick.com/articles/nurago-httpclient/</link><pubDate>Sat, 18 Jul 2026 00:00:00 +0000</pubDate><guid>https://tecnick.com/articles/nurago-httpclient/</guid><description>&lt;hr&gt;&#10;&lt;p&gt;Instrumentation has an observer problem. The moment you wrap an HTTP client to log requests, propagate trace IDs, and dump payloads for debugging, you have added code that can mutate the caller&amp;rsquo;s request, leak timers, buffer streams that were meant to flow, and write secrets to disk. The wrapper meant to explain production behaviour becomes part of it.&lt;/p&gt;&#10;&lt;p&gt;The &lt;a href="https://github.com/tecnickcom/nurago/tree/main/pkg/httpclient"&gt;&lt;code&gt;httpclient&lt;/code&gt;&lt;/a&gt;&#10; package in &lt;a href="https://github.com/tecnickcom/nurago"&gt;nurago&lt;/a&gt;&#10; wraps &lt;code&gt;net/http&lt;/code&gt; with trace ID propagation and structured request/response logging, and most of its design is about exactly this tension. Each section below is one place where observing a request could disturb it, and what the code does there instead.&lt;/p&gt;</description></item><item><title>Between Two Attempts: What an HTTP Retry Loop Must Decide</title><link>https://tecnick.com/articles/nurago-httpretrier/</link><pubDate>Sat, 18 Jul 2026 00:00:00 +0000</pubDate><guid>https://tecnick.com/articles/nurago-httpretrier/</guid><description>&lt;hr&gt;&#10;&lt;p&gt;A retry loop looks like the simplest code you will write all week: try, and if it failed, wait and try again. The hard questions live in the gap between one attempt and the next. Was that outcome worth retrying at all? What has to be released before another attempt is safe? Can the request even be sent a second time? How long is the wait, and who has the final say on it?&lt;/p&gt;</description></item><item><title>A Reverse Proxy Is Defined by What It Refuses to Do</title><link>https://tecnick.com/articles/nurago-httpreverseproxy/</link><pubDate>Sat, 18 Jul 2026 00:00:00 +0000</pubDate><guid>https://tecnick.com/articles/nurago-httpreverseproxy/</guid><description>&lt;hr&gt;&#10;&lt;p&gt;The engine of a Go reverse proxy is &lt;code&gt;net/http/httputil.ReverseProxy&lt;/code&gt;, and it is a good engine. What distinguishes one proxy deployment from another is almost entirely policy: what gets forwarded, what gets rewritten, what gets timed out, what gets logged.&lt;/p&gt;&#10;&lt;p&gt;In a proxy the characteristic failure mode is helpfulness. Following a redirect is helpful, and it is also a request-forgery vector. A whole-request timeout looks like a safety net until it truncates a long download. Logging everything drowns the one entry that mattered.&lt;/p&gt;</description></item><item><title>Before the First Request and After the Last: a Go HTTP Server's Edges</title><link>https://tecnick.com/articles/nurago-httpserver/</link><pubDate>Sat, 18 Jul 2026 00:00:00 +0000</pubDate><guid>https://tecnick.com/articles/nurago-httpserver/</guid><description>&lt;hr&gt;&#10;&lt;p&gt;Serving HTTP is the easy middle of a server&amp;rsquo;s life. &lt;code&gt;net/http&lt;/code&gt; handles it well, and it is rarely where the trouble starts. The places where a server can embarrass itself are the edges: the startup that half-works until the first request finds the misconfiguration, and the shutdown that drops in-flight requests, leaks a goroutine, or hangs the deploy. The &lt;a href="https://github.com/tecnickcom/nurago/tree/main/pkg/httpserver"&gt;&lt;code&gt;httpserver&lt;/code&gt;&lt;/a&gt;&#10; package in &lt;a href="https://github.com/tecnickcom/nurago"&gt;nurago&lt;/a&gt;&#10; is a bootstrap around &lt;code&gt;net/http&lt;/code&gt; (routing, middleware, operational endpoints, TLS, graceful shutdown), and its most interesting engineering lives at those edges, so that is where this post stays.&lt;/p&gt;</description></item></channel></rss>