HNHacker News
TopNewBestAskShowJobs

hxtk

508 karma · joined August 12, 2015

submissionscomments
hxtk··on You are how you act
The main resource that I recommend is the one towards the bottom of the comment: “Motivational Interviewing” by W.R. Miller and Stephen Rollnick. I’ve read the third and fourth editions. The third edition is more concrete but also more complex, and more focused on the field of clinical psychology, while the fourth edition is a shorter book where it’s been generalized more to be more applicable to all kinds of helping relationships, but contains fewer specific examples of clinical practice.

In the second edition they had not yet broken up the concept of “resistance” into “sustain talk” and “discord,” which I found to be a helpful distinction.

About 10% of the book is its bibliography, so if you want more information about a specific claim you can usually find the primary source by following the reference.

Miller and Rollnick are the ones who developed the technique of motivational interviewing, so they have a strong connection to much of the research cited.

hxtk··on You are how you act
There’s some real research into relevant topics and evidence-based models of how and why people change.

Generally, a period of ambivalence precedes change (most of the time, though there are documented cases of “quantum change” where a person undergoes a difficult change in a single moment without the usual intermediate stages and never relapses).

Ambivalence exists when a person knows in their mind reasons both for and against a change, and gives both more or less an equal mind share.

When that person begins to give an outsized share of their attention to engaging with thoughts aligned with the change, it predicts growing commitment and ultimately follow-through on the change.

The best resource I know of on this topic is “Motivational Interviewing” in its 3rd or 4th edition. It has a very extensive bibliography and the model of change it presents has proven itself an effective predictor of change in clinical practice.

Based on my understanding of that research, I’m inclined to agree with GP.

hxtk··on Build your own database
I think it was a joke. It sounds like you read it as append-only, like most LSM tree databases (not rewriting files in the course of write operations), but I think GP meant it as write-only to the exclusion of reads, roughly equivalent to `echo $data > /dev/null`
hxtk··on Io_uring is not an event system (2021)
Event-Driven Architecture refers to a different thing, but people used to refer to async code as event-based back before async/await existed, when doing async meant writing the Event Loop yourself.
hxtk··on TigerBeetle is a most interesting database
Meaning computationally. It would cost a lot of cycles to keep that enabled in production.

It’s only O(n), but if I check that assertion in my binary search function then it might as well have been linear search.

hxtk··on Ask HN: What are you working on? (September 2025)
I’ve been working on a few utility libraries to make it easier to develop web services, basically exporting packages that I find myself using or rewriting often and exporting them as their own modules.

I recently published https://github.com/hxtk/sqlt for SQL query generation with Go templates.

I’m working on https://github.com/hxtk/aip as a collection of libraries giving safe default choices to implement Google’s API improvement proposals in ConnectRPC services. It borrows (with attribution per the license) an unexported implementation of AUP-160 filters from the LuCI project, and I intend to expand it to support data sources other than SQL databases and page tokens, and it also exports an implementation of AIP-161 field masks (which have different semantics compared to standard field masks) and middleware to help with using them for AIP-157 read filtering. I intend to export more middleware that I use frequently, but I don’t know if it’ll live in this module or its own yet.

hxtk··on SSH3: Faster and rich secure shell using HTTP/3
It also gives you two authenticated protocol layers, which helps them because most standard protocols don’t support multiple authenticated identities. Their zero trust model uses it to authenticate each time you make a connection that your machine has authorization to connect to that endpoint via a client certificate, and then the next protocol layer authenticates the user.
hxtk··on Testing is better than data structures and algorithms
I’ve long wished for an SQL error model: given a schema, query, and transaction isolation mode, what errors are theoretically possible?

I have a hard time answering this for Postgres, which disappoints me because I don’t see any reason it sounds very easy to answer, like there could be an extension to EXPLAIN that would dry run the query and list all the error states reachable.

hxtk··on PgEdge Goes Open Source
If you're referring to the post from yesterday, they actually relicensed it as Apache 2.0: https://news.ycombinator.com/item?id=45196173
hxtk··on Serverless Horrors
I know AWS in particular does not because they do not increment the bill for every request. I don't know exactly how they calculate billing, but based on what I do know about it, I imagine it as a MapReduce job that runs on Lambda logs every so often to calculate what to bill each user for the preceding time interval.

That billing strategy makes it impossible to prevent cost overruns because by the time the system knows your account exceeded the budget you set, the system has already given out $20k worth of gigabyte-seconds of RAM to serve requests.

I think most other serverless providers work the same way. In practice, you would prevent such high traffic spikes with rate limiting in your AWS API Gateway or equivalent to limit the amount of cost you could accumulate in the time it takes you to receive a notification and decide on a course of action.

hxtk··on Busy beaver hunters reach numbers that overwhelm ordinary math
The algorithm for BB(N) is (with some hand waving) “for each N-state Turing machine, check if it halts on an initially empty tape. If it does not, skip it. If it does, run it until it halts and count the number of steps, k. BB(N) is the maximum value of k you find.”

The problem is that the naive algorithm above requires an oracle for the Halting Problem, which every CS student learns is impossible in general for a computational model that isn’t more powerful than a Turing Machine.

So if a function can be expressed in terms of a Turing machine, busy beaver has to grow faster because eventually for some value of N, you can just encode the candidate function as a Turing machine and have Busy Beaver simulate it.

Busy Beaver hunters on the low end (trying to find the next number) have to exhaustively prove whether each Turing machine eventually halts or not at that number of states so that they can evaluate the longest running one with finite execution.

hxtk··on 450× Faster Joins with Index Condition Pushdown
> against a key-value store no less, which probably fundamentally limits what optimizations can be done in any general way

I would disagree with this assumption for two reasons: first, theoretically, a file system is a key value store, and basically all databases run on file systems, so it stands to reason that any optimization Postgres does can be achieved as an abstraction over a key-value store with a good API because Postgres already did.

Second, less theoretically, this has already been done by CockroachDB, which stores data in Pebble in the current iteration and previously used RocksDB (pebble is CRDB’s Go rewrite of RocksDB) and TiDB, which stores its data in TiKV.

A thin wrapper over a KV store will only be able to use optimizations provided by the KV store, but if your wrapper is thick enough to include abstractions like adding multiple tables or inserting values into multiple cells in multiple tables atomically, then you can build arbitrary indices into the abstraction.

I wouldn’t tend to call a KV store a bad database engine because I don’t think of it as a database engine at all. It might technically be one under the academic definition of a database engine, but I mostly see it being used as a building block in a more complicated database engine.

hxtk··on Code review can be better
CS is sort of unique in that regard. I value my university degree, but when I think about the classes that helped me the most, only one of them was a degree requirement. Not because the degree was useless, but because the information was accessible enough that I already knew most of the required content for an undergraduate degree when I got there.

I took lots of electives outside my major, and I know that I could have easily loved chemistry, mathematics, mechanical engineering, electrical engineering, or any number of fields. But when you're 12 years old with a free period in the school computer lab, you can't download a chemistry set or an oscilloscope or parts for building your next design iteration. You can download a C compiler and a PDF of K&R's "The C Programming Language," though.

CS just had a huge head-start in capturing my interest compared to every other subject because the barrier to entry is so low.

hxtk··on Streaming services are driving viewers back to piracy
Streaming services were great back when they were separate from content producers and IP holders.

Once every media company became a streaming company and started using anticompetitive licensing practices in an attempt to drive viewership to their own platforms, the market fractured too much for it to be profitable.

Something smells “prisoner’s dilemma” about it: the best move for any individual streaming service is to have exclusive content (and the best-positioned players to do that are the studios), but when everyone does that, it decreases the overall profit available in the market more than it increases their slice of the pie.

hxtk··on Problem solving using Markov chains (2007) [pdf]
A Markov process is any process where if you have perfect information on the current state, you cannot gain more information about the next state by looking at any previous state.

Physics models of closed systems moving under classical mechanics are deterministic, continuous Markov processes. Random walks on a graph are non deterministic, discrete Markov processes.

You may further generalize that if a process has state X, and the prior N states contribute to predicting the next state, you can make a new process whose state is an N-vector of Xs, and the graph connecting those states reduces the evolution of the system to a random walk on a graph, and thus a Markov process.

Thus any system where the best possible model of its evolution requires you to examine at most finitely many consecutive states immediately preceding the current state is a Markov process.

For example, an LLM that will process a finite context window of tokens and then emit a weighted random token is most definitely a Markov process.

hxtk··on LLM Embeddings Explained: A Visual and Intuitive Guide
I thought that the point of replaceState was precisely to avoid appending elements to the history, and instead replace the most recent one, so I think I must be missing something if that line causes lots of additional history items.
hxtk··on Keep Pydantic out of your Domain Layer
The main “why” that I find is that it allows you to intentionally design your API types and know when a change is touching them.

I worked on a project with a codebase on the order of millions of lines, and many times a response was made by taking an ORM object or an app internal data structure and JSON serializing it. We had a frequent problem where we’d make some change to how we process a data structure internally and oops, breaking API change. Or worse yet, sensitive data gets added to a structure typically processed with that data, not realizing it gets serialized by a response handler.

It was hard to catch this in code review because it was hard to even know when a type might be involved in generating a response elsewhere in the code base.

Switching to a schema-first API design meant that if you were making a change to a response data type, you knew it. And the CODEOWNERS file also knew it, and would bring the relevant parties into the code review. Suddenly those classes of problems went away.

hxtk··on Air Force unit suspends use of Sig Sauer pistol after shooting death of airman
Off by one errors strike again, unless you EDC a machine pistol?
hxtk··on Axon’s Draft One is designed to defy transparency
I really wish policing would take more inspiration from aviation on a different avenue for police accountability.

The NTSB exists not to blame pilots (though they sometimes do), but to make air travel safer and prevent future plane crashes. In the business of preventing disaster in safety-critical industry, if you chalk something up to human error or call it a tragic accident, you guarantee that it will happen again. Finding that everyone did everything by the book means the book needs to be rewritten because the book that exists today contains a recipe for plane crashes.

I wish police would treat use of force incidents the same way. The investigations after police use of force ask whether the officer violated the law or department policy. Like most law enforcement and judicial work, the exercise focuses on identifying, trying, and punishing guilty parties. If there is no guilty party, the process can produce no change. I would like to see more investigations into police use of force that focus on improving safety outcomes instead.

hxtk··on Ptar: Replacing .tgz for petabyte-scale S3 archives
I’ve worked on a project with strict legal record-keeping requirements that had a plan for the primary AWS region literally getting nuked. But that was the only contingency in our book of plans that really required the S3 backup. We generally assumed that as long as the region still existed, S3 still had everything we put in it.

Of course, since we had the backups, restoration of individual objects would’ve been possible, but we would’ve needed to do it by hand.

hxtk··on uv: An extremely fast Python package and project manager, written in Rust
If you specify your constraints in pyproject.toml like this: `package1==0.4.0`; then that is the latest (and only) version satisfying your constraints. Not upgrading is expected behavior, because upgrading would violate constraints.

pyproject.toml’s dependency list specifies compatibility: we expect the program to run with versions that satisfy constraints.

If you want to specify an exact version as a validated configuration for a reproducible build with guaranteed functionality, well, that’s what the lock file is for.

In serious projects, I usually write that dependency section by hand so that I can specify the constraints that match my needs (e.g., what is the earliest version receiving security patches or the earliest version with the functionality I need?). In unserious projects, I’ll leave the constraints off entirely until a breakage is discovered in practice.

If `uv` is adding things with `==` constraints, that’s why upgrades are not occurring, but the solution is to relax the constraints to indicate where you are okay with upgrades happening.

hxtk··on Git Notes: Git's coolest, most unloved­ feature (2022)
Your understanding of the Change-Id footer sounds like it matches mine.

I’d note that it works that way presently, but the teams behind git, gerrit, jj-vcs, and a couple of other relevant stakeholders have an email thread going in which, from what I understand, they discuss standardizing on the approach taken by jj-vcs:

https://lore.kernel.org/git/CAESOdVAspxUJKGAA58i0tvks4ZOfoGf...

hxtk··on Git Notes: Git's coolest, most unloved­ feature (2022)
GitLab is actively developing native support for stacked diff workflows. CLI support for creating stacks landed in GitLab 17, and now they’re working on the code review workflow for it.

To be honest, though, I find it easiest to create several branches with Jujutsu and then manually chain the MRs. That’s what glab does under the hood with glab stack commands. Looking forward to the code review tools in a future version.

For GitHub, though, I think Graphite is the best tool I’ve looked at so far, but I use GitLab at work so I’m not the best judge of GitHub tools for lack of experience using them at scale.

hxtk··on Apple's Liquid Glass is prep work for AR interfaces, not just a design refresh
Honestly I thought I’d hate it, but if I get the transparency just right where it’s not distracting but I can still see read through it if I try, I do find that it helps when I find myself lacking screen real estate.

I’d still rather have an opaque terminal and just get a second monitor, but that’s not always an option.

hxtk··on Apple's Liquid Glass is prep work for AR interfaces, not just a design refresh
I’ve definitely been preferring a transparent background on my terminal lately, particularly when I only have one screen, because it increases my ability to read the reference material I have opened behind it. At the very least, if I have to alt-tab it out of the way, I’m already oriented on the page. So I can see the benefit in at least some use cases.

I don’t think I’d like to have it on everything, though. Or basically anything except my terminal, for that matter.

hxtk··on Washington Post's Privacy Tip: Stop Using Chrome, Delete Meta Apps (and Yandex)
I tend to use Safari on my mac, but I will say that it evaluates CORS slightly differently than other browsers so that sometimes I have to disable CORS protection to get a site to work that works fine in Chrome or Firefox, and it's the only browser I've used where I expect to have it crash hard with a SEGFAULT or something every once in a while.
hxtk··on An Interactive Guide to Rate Limiting
I notice that library self-identifies a problem of generally keeping a fixed-size number of buckets and addressing them with hashing, which leads to great memory usage but introduces a risk of collision.

Stochastic Fair Blue shares that problem, so I think you might find the solution it uses interesting: it rotates hashes on fixed intervals by re-seeding to ensure that if a responsive flow collides with a non-responsive flow that's being rate-limited, it is at least guaranteed not to do it for very long.

This leads to a problem similar to the problem with Fixed Window Counter rate limiting where it would basically forget the rate limit history every interval. To solve this, two queues are fed input data at a time: the router enforces one of them, while just feeding the other data and ignoring its output in order to warm up its buckets.

I imagine if I tried to make use of the library you linked and didn't absolutely need per-user granularity, I'd do something similar by concatenating the user's identifier with a seed value for each of the two queues and rotating at regular intervals.

hxtk··on An Interactive Guide to Rate Limiting
Something I’ve long wondered is why you never hear about rate limiting algorithms that are based on the cost to serve the request or algorithms that dynamically learn the capacity of the system and give everyone a fair share.

In the field of router buffer management, there are algorithms like Stochastic Fair Blue, which does the latter, but is somewhat hard to apply to HTTP because you’d have to define a success/failure metric for each request (a latency target, for example), and clients would have to tolerate a small probability a request being rejected even when they’re not being rate limited.

In Google’s paper on the Zanzibar authorization system, they give brief mention to rate limiting clients based on a CPU time allocation, but don’t go into any detail since it’s not a paper on rate limiting.

It’s something that matters less today with ubiquitous autoscaling, where the capacity of the system is whatever you need it to be to give each user what they ask for up to their rate limit, but I’m surprised at my inability to find any detailed account of such a thing being attempted.

hxtk··on Show HN: Kan.bn – An open-source alterative to Trello
This isn’t something I’ve found with NextJS, but I also haven’t tried a lot of other, similar frameworks because I’m mostly a backend and SRE person who just learned NextJS so I could throw together pretty UIs to demo my backend ideas, so maybe I’m missing things that are well known among front-end specialists.

My experience is that a basic deployment is very easy—it’s like a ten line Dockerfile to build a distroless nodejs container of the standalone build and if you deploy it, it just works.

Then, as performance demands grow, there’s increasingly more complexity in the efforts that must be taken to squeeze additional performance out of it. An easy win is to host the static resources more efficiently with a static file server or better yet a CDN.

A more complex performance optimization is to implement caching.

At some point you start thinking about how to separate the middleware execution from the app so that it can be hosted in more regions or at the edge.

Vercel provides all of those optimizations for free in terms of operational complexity, and charges a lot for it monetarily, but it’s not all that surprising to me that when I host an application it takes some effort to get performance and feature parity with a dedicated hosting provider for that service, just like how I am not surprised that RDS is a little more complicated, more performant, and more reliable than renting the equivalent EC2 and installing Postgres from the package manager.

Caveat: as a backend dev, I’ve never written anything that relied entirely on NextJS as the server side, so I’m approaching this with a certain amount of baseline complexity already assumed. I’ve not touched NextJS static sites or incremental static regeneration.

Do other frontend frameworks make it much easier to incorporate those performance optimizations? My impression is that it’s not all that hard to deploy NextJS, it’s just hard to manage the complexity of optimizing it to the extent that Vercel’s hosting does.

hxtk··on As a developer, my most important tools are a pen and a notebook
> I use to just lose my notes.

I used to do this very intentionally. In the past, I've found that taking notes is very valuable for me, but having notes seldom is.

When I was in school, I would write all my notes on a dry erase board and simply erase it when I had filled up the page. That was when I was studying things that were already known, though, so it was viable to, for reference material, just become skilled at referencing pre-existing reference material.

Now that I'm a professional and often working on something new or combining things in a new way, it's more often useful to me to generate new reference content for myself and especially for a different person who picks up the task on my day off.

← PreviousPage 3 of 6Next →