Harry Brundage's Avatar

Harry Brundage

@airhorns

Developer developer. CTO at https://gadget.dev working on bringing some speed back to makin' software. Previously at Shopify

135
Followers
579
Following
34
Posts
06.12.2024
Joined
Posts Following

Latest posts by Harry Brundage @airhorns

Apollo 11 was 1969, where is software engineering’s claim to fame?

14.10.2025 14:00 πŸ‘ 2 πŸ” 0 πŸ’¬ 1 πŸ“Œ 0

As an industry we kinda deserve to be automated away in some ways β€” we’ve spent decades rehashing the exact same ideas 18000 different ways and made so little progress in actually wrangling complexity

14.10.2025 14:00 πŸ‘ 1 πŸ” 0 πŸ’¬ 1 πŸ“Œ 0
Preview
Build a Discord support bot from scratch Demo I always found it annoying when I was following a tutorial, and they didn’t show you...

It's too hard to build a Discord bot. Anything where YOU have to worry about hosting and scalability is too hard.

Here's the solution: dev.to/gabeb03/buil...

16.09.2025 13:47 πŸ‘ 6 πŸ” 1 πŸ’¬ 0 πŸ“Œ 2

For colour, there was The Wizard of Oz, for AI feature length films, there will be ... ? And will there be riots or rejoicing?

19.06.2025 14:00 πŸ‘ 1 πŸ” 0 πŸ’¬ 0 πŸ“Œ 0

Did you know that abstraction is bad actually for performance

18.06.2025 14:00 πŸ‘ 0 πŸ” 0 πŸ’¬ 0 πŸ“Œ 0

Spent a lot of time developing a high-throughput, durable, distributed semaphore at Gadget

Can you guess what data store we ended up using

11.06.2025 14:00 πŸ‘ 0 πŸ” 0 πŸ’¬ 0 πŸ“Œ 0

Temporal is super neurotic about determinism which creates a lot of friction for me, and these systems seem to have taken a much more pragmatic approach. I wonder if win or huge burn

09.06.2025 14:00 πŸ‘ 0 πŸ” 0 πŸ’¬ 0 πŸ“Œ 0

Anyone who’s used inngest or trigger dot dev in depth β€” how do you change workflow definitions after they’re already running? Is is hard to do safely?

09.06.2025 14:00 πŸ‘ 0 πŸ” 0 πŸ’¬ 1 πŸ“Œ 0

Narry a spanner in sight!

Only exception is etcd for k8s coordination, which, sadly, is high throughput at Gadget also

07.06.2025 14:00 πŸ‘ 1 πŸ” 0 πŸ’¬ 0 πŸ“Œ 0

For real though, Temporal, turbopuffer, alloydb, bigtable, kvrocks, Postgres/AlloyDB are our weapons of choice at Gadget β€” all work this way.

If you want hella scalable performance, you shard horizontally and prevent the shards from having to co-ordinate on the data plane.

07.06.2025 14:00 πŸ‘ 0 πŸ” 0 πŸ’¬ 1 πŸ“Œ 0

All the cool new high throughput systems I use contend over node-local locks for writes -- no distributed consensus like Raft or Paxos

Consensus is out on consensus amirite

07.06.2025 14:00 πŸ‘ 0 πŸ” 0 πŸ’¬ 1 πŸ“Œ 0

Stand by it still

06.06.2025 13:57 πŸ‘ 0 πŸ” 0 πŸ’¬ 0 πŸ“Œ 0

One time I think I made someone quit by saying that no, global variables are good actually.

06.06.2025 13:57 πŸ‘ 0 πŸ” 0 πŸ’¬ 1 πŸ“Œ 0
Preview
GitHub - gadget-inc/mobx-quick-tree: A mirror of the mobx-state-tree API that supports creating a fast, non-reactive, read-only tree A mirror of the mobx-state-tree API that supports creating a fast, non-reactive, read-only tree - gadget-inc/mobx-quick-tree

We do this second one in github.com/gadget-inc/... a lot and it sucks -- a lot of nasty string => code grossness but it really, really works.

05.06.2025 14:00 πŸ‘ 0 πŸ” 0 πŸ’¬ 0 πŸ“Œ 0

There’s only two ways I really know how do that: write out type-specific versions of functions by hand, with individual variants that only ever work with the same types. Or, manually craft and eval these variants dynamically at runtime for a lightweight JIT of your own

05.06.2025 14:00 πŸ‘ 0 πŸ” 0 πŸ’¬ 1 πŸ“Œ 0
Preview
GitHub - thlorenz/deoptigate: ⏱️ Investigates v8/Node.js function deoptimizations. ⏱️ Investigates v8/Node.js function deoptimizations. - thlorenz/deoptigate

The fix is to make monomorphic code, which means each expression only ever takes on one type so the JIT can be aggressive. I use github.com/thlorenz/de... for profiling to find megamorphic callsites.

05.06.2025 14:00 πŸ‘ 0 πŸ” 0 πŸ’¬ 1 πŸ“Œ 0

Different values of different types pass through them all the time, so v8’s JIT can’t make assumptions and optimize stuff away and has to leave slower code that checks the type to make sure things are as it expects or if there are many different callees

05.06.2025 14:00 πŸ‘ 0 πŸ” 0 πŸ’¬ 1 πŸ“Œ 0

The one line of code within debounce that calls the function you passed in is always on the same line, but if you've debounced more than one function, that callsite calls one of many of the functions you've passed it -- the type of the call is not static every time that expression is evaluated.

05.06.2025 14:00 πŸ‘ 0 πŸ” 0 πŸ’¬ 1 πŸ“Œ 0

But generic wrapper functions or utility functions like denounce, memoize, and pretty much all the other stuff in lodash don’t have consistent input types because they are used and reused in a wide variety of different contexts!

05.06.2025 14:00 πŸ‘ 0 πŸ” 0 πŸ’¬ 1 πŸ“Œ 0

Usually if you’re writing concrete functions, like leftPad or what have you, the input types and intermediate expressions all always have the same type when executed (String), which leads to good optimization

05.06.2025 14:00 πŸ‘ 0 πŸ” 0 πŸ’¬ 1 πŸ“Œ 0

In V8 at least, function callsite optimizations make a HUGE difference, but AFAIK, the optimizations are applied to lexical callsites either entirely or not at all. Function call overhead can only be removed fully if the types of the variables flowing through a call site are always the same

05.06.2025 14:00 πŸ‘ 0 πŸ” 0 πŸ’¬ 1 πŸ“Œ 0

🧡 JS perf nerdery I always get tripped up on: generic wrapper functions really kill performance hard because they create megamorphic call sites.

Fun word, unfun impact.

05.06.2025 14:00 πŸ‘ 0 πŸ” 0 πŸ’¬ 1 πŸ“Œ 0

The entire software dev industry was built when code was scarce and expensive to create. Scarcity is over, now it’s about trust -- whole industry needs to change.

04.06.2025 13:59 πŸ‘ 1 πŸ” 0 πŸ’¬ 0 πŸ“Œ 0

App dev has been set back 10 years by a simple confusion between app dev and web dev. next.js / remix have to play the make-e-commerce-sites-fast game instead of the make-building-the-next-figma-fast game and it really shows.

03.06.2025 14:00 πŸ‘ 0 πŸ” 0 πŸ’¬ 0 πŸ“Œ 0

What’s your favourite rich filtering UI? For the demon index view in your app with 9 different possible attributes that can be filtered in tandem 18 different ways? The best I’ve used is Postico but … there has to be a better way

02.06.2025 16:57 πŸ‘ 0 πŸ” 0 πŸ’¬ 0 πŸ“Œ 0

What are your favourite patterns for enqueuing up backend work items that need to then be processed in batches for efficiency? Think like batch submission of inventory updates to a poopy low rate limit api such that you need to debounce, but on the backend statefully

02.06.2025 14:04 πŸ‘ 1 πŸ” 0 πŸ’¬ 0 πŸ“Œ 0

Last time I felt as giddy as I do when vibe coding was my first ever visual basic app. Seismic shifts afoot people, seismic.

31.05.2025 13:57 πŸ‘ 1 πŸ” 0 πŸ’¬ 0 πŸ“Œ 0

The edge lords were wrong - turns out RTT to the database matters more than RTT to the user

30.05.2025 13:58 πŸ‘ 0 πŸ” 0 πŸ’¬ 0 πŸ“Œ 0

Claude 4 is very good -- yes indeed. They RLHF’d a little too close to the sun and every third statement has a try/catch around it now

29.05.2025 21:35 πŸ‘ 0 πŸ” 0 πŸ’¬ 0 πŸ“Œ 0
Building a Discord bot fast with Gadget's AI
Building a Discord bot fast with Gadget's AI Gadget's CTO Harry builds a Discord bot using Gadget to help out in Gadget's discord. What fun!

Gonna livestream building a AI-powered Discord bot using Gadget tomorrow at 10:00 AM EST here:

www.youtube.com/watch?v=xTH...

Swing by if you wanna nerd out!

23.05.2025 21:30 πŸ‘ 0 πŸ” 0 πŸ’¬ 0 πŸ“Œ 0