We should've stopped--but let's keep going and see what happens.

Getting Toasty: Observations on Burnout

I’ve yet to see a really good essay by anybody who isn’t a developer talking about engineer burnout. JWZ, Rachel Kroll, or cbloom (back before he zorched his rambles) are all good examples, but otherwise I haven’t seen a lot else.

I’ll add some data points to it, go in-depth on what I think causes it, and attempt to offer some advice for engineers and managers.

Important note 1: This is all very heavily-based on my own experiences, as a beginner up to now senior developer with experience bootstrapping (and failing), hiring, and growing teams, and grinding on terrible projects. My experience may not match yours. That’s cool. Go write your own blog post about it and help bring sunlight to a nasty topic.

Important note 2: Burnout sucks. This should be discussed solemnly in person, on IRC, or over email, but until that’s more common maybe this will help people find a starting point. I’m sick of self-serving Medium articles and Twitter circlejerks with people singewashing their experiences for pageviews.

Examples and stories of burnout

Three example stories I’ve collected, redacted to one degree or another, none are me (that’s a different section):

  • Dev works at game company in crunch, postpones sleep, eventually starts seeing noses on everything. His own hands. Car’s dashboard. Trees. Finally stops after a couple of weeks of sleep.

  • Dev works at a startup, spends a couple hours every week on a couch just kinda staring into space. Eventually quits, won’t talk to folks from that gig.

  • Dev works at older software company, one day stabs self in the neck with a writing implement in the lobby of employer and bleeds out until paramedics get there.

Note that those are the final battles of whatever war the people were fighting—healthy people don’t exhibit those behaviors unbidden overnight.

Things I personally have done, witnessed, or handled the fallout from:

  • Dev quits immediately after finding out a long-requested performance review was done mainly to fire a coworker.

  • Dev under massive pressure from outside of work runs late for a standup and gets really flustered. Is taken for a walk to clear their head and reassured that nothing is as bad as feared.

  • Dev breaks down crying in front of execs after crunch to get last part of a project finished—during demo, only feedback was “why is x missing”.

  • Dev accuses management of lying during team lunch, is invited to meet the following hour, puts in one month’s notice and leaves. Is unable to program for a few months for any reason without getting irrationally angry.

  • Dev disappears into the mountains to avoid any chance of contact for a few days during a critical deliverable just to get away from business pressure. Contractors cheerfully negotiate weekend, active-fire rates.

Listed as sanitized bullet-points, these stories look out at us from the monitor as flaccid little factoids. One of the things you have to understand is that, from the outside, any individual case of burnout looks really uninteresting.

To get the full picture, you have to get on the inside of the situations. What I’ve left out here is the context for each one, the people involved, the projects, the companies. Sometimes I’ve done that out of respect for the parties involved, sometimes because it’d take to long to explain, and sometimes because I frankly can’t really figure out how to go into the story in a way that wouldn’t distract and detour from the rest of this post.

It took me a few months after quitting my last job to start being able to open up about what happened (a story for another time). Interestingly though, to me, that in short order I ended up with a few friends over hot chocolate (caffeine being bad for the nerves for a lot of us) exchanging these stories—people with careers half as long, twice as long, the same length…everywhere I probed, I could usually find somebody with a story.

That’s scary as fuck.

Who gets hit?

Angersock,” you might say, “this is something that just happens to those wacky folks chasing the dream out in the Bay area, or to already unwell individuals experiencing the stresses of business.

To this, I say no. Those stories? Hardworking folks, recovered to varying degrees (I think) thankfully. All happened in flyover country in nominally pretty normal populations. These aren’t the folks you’d expect from some freewheeling, white-hot Valley VC pump-and-dump gamble, but folks doing relatively straightforward work for normal pay and with only occasionally weird environments.

I’d like to be able to claim that there was some pattern to it, some demographic at risk beyond “do you sling code for a living?”. Alas, I haven’t found one. I’ve seen this happen to both men and women, gay and straight, cis and trans, young and less young, left and right, single and paired, and it keeps happening to some poor soul regardless of where they fall in that lineup.

In a way we can find that both scary and reassuring since it implies that the damage comes from a working environment and not something in the makeup of the person. If we can figure out what environments lead to burnout, maybe we can repair it or at least recognize when it’s happening.

Anatomy of a burnout

Two major areas of suffering are required to cause burnout: the work, and the environment.

Work factors for burnout

The work that I’ve seen lead to burnout tends to be:

  • All-consuming
  • Uninteresting
  • Lacking visible progress indicators
  • Lacking a clear end date

Let’s take an adversarial approach to this and pretend we’re trying to design work to maximally distress our developers.

All-consuming work is work that takes priority over everything else. The occasional shitty gig or task is annoying or inconvenient, but for burnout to happen the work itself must eclipse every other thing in the developer’s working life. Writing from an American perspective, knowing that many workers are probably putting in 8-9 hours a day at their job, it’s important to note that this means that something like a third of their daily life-force is being taken up by a project. If you decide to do your accounting to focus just on time spent awake, then the bloody thing is taking up, at minimum, half of their waking time (assuming they’re getting enough sleep).

And here’s a dirty secret: if they’re younger or more “passionate” or frankly just plain single, they’re probably going to give even more waking hours over to their work because there are fewer competing demands on their time.

So, if things start going south with the work, it’s easy to see that there just isn’t an escape from it. Lucky for us, this is the cultural norm and expectation in the US, and so we don’t actually have to go out of our way to make the work permeate every part of their life.

Uninteresting work is work that does not stimulate the exploring or learning modes of the worker. This is a slippery one, because it sounds a little too much like whining that “oh gee this is so boring, I’d rather learn a new JS framework.” The typical response to that cry is “well, not all of us get to do fun work.”

However, fun is precisely not what I mentioned—uninteresting work is uninteresting because it is predetermined and doesn’t help the developer grow. Examples of this work that I’ve seen include:

  • Many UI/UX projects (design given, implementation delivered, testing done, tweak suggested, repeat) on the same interface, over and over again (because selling something is harder than polishing a turd and so biz will chase that instead of just selling harder).

  • Gradual refactoring of a codebase, where each individual step is trivial but there’s just so many of them—and this is why big-bang rewrites often happen, because that’s just less terrible than trying to mop up a floor with a muddy mop.

  • Bringing a large codebase into compliance with a style guide, though this is a lot less terrible than it used to be due to tooling improvements.

  • Constantly keeping on top of a codebase that’s changing out from under you, which easily happens if you work on a long-running feature and others are in the same codebase. Fixing conflicts isn’t hard, it’s just tedious and you are often rewarded with…more conflicts!

  • Bughunting and ops stuff, once you’ve gotten the hang of things. The only “new” info you ever learn about a production system is that it is broken or, even worse, that it is somehow managing to deliver value despite having the software equivalent of hyperdimensional aggressive bone cancer. Instead of merely not affording chances to learn or explore, this work actively punishes you for digging into the abyss.

Lacking visible progress indicators is part of work that disorients and confuses the worker. At this point, our dev is on a project that is consuming most of their waking hours and is doing something that is not causing them to explore or learn. So, next, let’s take away their frame of reference and make it so that the work that they are doing never appears to get any further along.

If it’s UI work, constantly send it back for rework so that they never see progress, only change. If it’s ops work, don’t track a baseline to make it easy to see if the system is getting more stable or less stable. If it’s refactoring work, the entire point is that to an external observer nothing is different regardless of how much effort was expended.

We can also modify our process to make this even easier: have product managers intermediate the developer’s exposure to customers. Use story points and chop up tasks into small Jira tickets so that it’s hard to piece together the overall view of where a project is going—and never, ever use thorough acceptance criteria to give developers a way of seeing when they’ve actually delivered what needed to get done.

Remember, you never want the developer to hit a wall or stop, because that is actually a useful form of feedback. Instead, you want them to continually spew life force out into the all-consuming maw of your project in such a way that maybe, just maybe, this feature will be enough to move the needle and get them unstuck. Humans are very responsive to this.

In short, the developer should never feel like their actions have any actual positive impact on the state of things but should have just enough hope that maybe the next time will be different.

Lacking a clear end date is how to get work that cannot be bounded in its suffering. If you have a hard day serving coffee or working the help desk, at the end of your shift the work is over and done, and however bad things are they end. If you tell somebody that they only need to hold out for six more hours before dinner, they’ll get hungry but they can pull it off. A project with a hard deadline of launching on Christmas day, while stressful in its own right, is out of the hands of everyone December 26th.

To really grind the bastards down, you want to make sure that there is no strong timeline that can be used to internally gird themselves. If the developer can say “Well, if I can make it to launch this week, everything will be fine or at least it will be over” then they may be able to hold out long enough to see themselves through to the other side of a bad project. Instead, prefer to constantly renegotiate deadlines and “buy extra time” to keep a purgatory project going.

Why do this?

The most jaded developer will call upon deep wells of fatalism and make their peace with a project failing, write it off, and square themselves to face things anew. They may be able to make their peace with impending failure and start planning the next project or their next gig. If you keep extending the project, though, there is no chance to write off the future. There is no opportunity to heroically make one last desperate push. There is just a modified Gantt chart stamping on a programmer’s face, forever.

Further, you can cleverly increase even further the internal pressure a developer is under. If you refuse to fire them, but you also refuse to let the project die, they are forced to work on something that is traumatizing them knowing full well that the only escape is to either finish the project (unlikely) or quit themselves (unsatisfactory).

Given this option, many developers will double down and become their own kapos, prisoners to their work but foolishly believing that they are doing so of their own free will and that the work has some intrinsic value to them—after all, it that wasn’t the case, why would they be doing it? The most prideful and otherwise wily programmers can be thus brought into line.

Environment factors for burnout

Let’s take off our adversarial hat, fun though it is for the rhetoric, and just talk plainly about environmental factors outside the work itself.

Some environmental factors I’ve seen lead or contribute to burnout are:

  • Lack of non-work havens
  • Health issues
  • Lack of non-work support networks and preoccupations
  • External reminders of happiness and progress

Lack of non-work havens is faced by developers who basically split their lives between an uncomfortable home and a soul-sapping office. Without a home, cafe, bar, park, museum, library, or space to unwind and relax, there is no opportunity to let the mind unwind and stop thinking about the project. There is no place to “find zen”, no place to force a shift to some other modality of thought, no way of telling the body “hey we’re in a place with stimnuli that do not mimic the place that we’ve come to associate with this project that is slowly eviscerating us.”

This can get really gnarly for remote workers, and one of the most common bits of advice shared is to make a dedicated space for work and to also leave it and get out of the house. Further, spending time “getting away” from work only to be surrounded by people talking about the startup hustle or similar project material can ruin any benefit from leaving your work—instead it’s followed you and is reminding you of what you were doing!

One unfortunate wrinkle on this is that a lot of young engineers, due to preference or due to finances, tend not to settle down in a super comfortable place. They may have super long commutes, they may live in a tiny cramped space, they may not spend cycles cleaning, they may have roommates—all of these are things that can make staying longer at work seem reasonable or desirable. I was one of those engineers, and only after finally getting my own place and making a concerted effort to transform it from being a house containing angersock to being angersock’s home did I find relief to a stress I didn’t know that I had.

Health issues can exacerbate burnout. Chronic fatigue, bad sleep, low energy, and any physical factors that get in the way of enjoying time away from work hurt us. Developers with depression or anxiety suffer even more during burnout, because they’re already operating with a handicap in terms of being able to fairly evaluate their own work—and as we saw above, perspective is a key component of what makes work induce burnout.

Believing that we don’t deserve to work on better projects, believing that the world will come crashing down (and if we’re under financial stress, that’s not an unfounded concern even before mental health enters into it!) if the project is abandoned or we don’t deliver, believing that if we stop working on a project we have failed ourselves or our mentors or our parents or our partners or the people who support us…all of these things make each low point lower in turn exacerbating the burnout.

While those beliefs are, I think, common in one form or another to any healthy person, folks at risk may take them to a point of rumination ) and be unable to find respite until something causes a drastic change of circumstances.

Lack of support networks again help prevent the formation of useful frame and perspective. Without having people outside of the project to confer with and socialize with, we lose the ability to keep the project at the right level of importance in our life. Without a hobby or stimulating activity to give us alternatives to work, many of us will keep devoting cycles to worrying about the project and trying to sink effort into it—and left unchecked, will often start to abandon support networks and activities in order to free up time to push past the rough spot in the burnout. This of course never works, because the projects usually don’t allow for it (again, see above).

Compounding this is the fact that many of us have switched cities or locations away from family or friends in order to work on our current gigs. Many of us are also engaged in “startup community” activities that frankly boil down to little more than drinking together and trying to sell each other on a vision of success that none of us are living. Such activities only serve to alienate us from people who, were we all a bit more open and honest about our struggles, might be able to at least remind us that whatever thing we’re stuck doing, it can’t be that bad. This is all aggravated by the absurd NDAs and fear of blackballing that all of us have in this sector.

External reminders of happiness and progress are, as mentioned in the preceding section, also sources of burnout. They themselves aren’t what does it, but if you’re already feeling hopeless and spread thin and worried about your progress seeing constant messaging about how the lifestyle is successful (for everybody but you), how hard work is the way to a massive exit (for everybody but you), and how much everybody (but you) is enjoying things and killing it does nothing but make your struggle seem more pointless and your own inadequacy larger.

Of course, there is no end to this messaging. Even setting aside the massive industry of entrepreneurship porn—which is all around us if you’re doing startup or software work—the simple fact is that the culture of our sector is not about helping others for their own sake nor about introspecting on projects and learning how to responsibly manage them. The mythos of our industry is rooted in the lone engineer or small team heroically fighting all odds to deliver a project seemingly through sheer force of will alone, and we judge ourselves and expect to be judged according to the same metric.

So, when I’m going through burnout I see people succeeding and not helping, and I expect to be treated like a pariah. And at some level, we all know that that is what will become of us if we stay in that way for too long; and that threat reinforces the fears of losing our support networks and our safe spaces.

Recovering from burnout

In my experience, recovering from burnout requires getting as far away from the work as is feasible and reestablishing perspective. Burnout takes as while to set in, and getting out of it takes a time as well. In one case it took three months before I could open an editor without slamming it shut, cursing the very idea of writing code.

Reestablishing perspective often means hitting those things we talked about each by each and fixing them or trying to do the exact opposite. To kind of recap some of them in a convenient bullet form. For the work stuff:

  • Work on projects that can be picked up and put down with no sense of urgency. If you feel like you’re “forcing” the project, or just slipping into flow and letting it cut into your time, step away from it and come back later. Reassert that you have a life outside the project.
  • Learn something new or go do some completely exploratory/fun work, preferably completely unrelated to the source of burnout. Maybe that’s a raytracer, maybe that’s writing stories about bunny rabbits, maybe that’s fishing.
  • Work on something that immediately rewards your effort, like building a workbench or baking some cookies or cleaning your home. Do literally anything that shows a clear and irreversible state change due to your own actions. Find a reminder that progress is something that actually exists.
  • Do something with a clear end date, and walk away. Say “I will try a hackathon” or “I will build a model this afternoon” or “I will write a poem” and then walk away or burn it once the time is up. Forcibly close it out.

For the environment stuff:

  • Find a happy place or make one, and spend time there without your burnout project. Find a park and enjoy an afternoon, move all your work crap into your home office and organize the rest of the house, go out to a rave—just do anything to find a place that hasn’t been psychically tainted by your burnout or project.
  • Work on your health issues. If you’re depressed or anxious, find a good therapist—hell, do that anyways. If your body isn’t doing what you want it to do, start working with it. If you’ve been putting off a surgical procedure, get it taken care of.
  • Find a hobby and people disjoint from your work (and from tech sector). Go to church, go dancing, go to meetups for basket weaving or art, go on dates. Have movie nights with friends, get in arguments with people online, do whatever it takes to block out headspace that work and burnout is not allowed to seep into anymore.
  • Stop paying attention to people in the tech sector. Stop following Hacker News and TechCrunch and ProductWatch and all of that other bullshit. Stop going to meetups where startup hopefuls lie to each other. Talk to people that can offer perspectives and offer sympathy without needing to worry about causing future career issues for yourself.

Those are just some ideas and things that’ve worked for me. If you find success some other way, do that instead. More importantly, talk to other people about what they’re going through on projects, and try to spot if they’re in a similar position and try to help.

We’re all in this together.

Language Features for Non-programmers


Schlub is a language designed to avoid or make impossible as many excesses of modern languages as possible while offering features to be more productive to business users. It does this by:

  • Providing data types suitable for engineering, mathematics, and statistical work
  • Enforcing the constraints of dimensional analysis when doing computations
  • Requiring specification of precision for numerical operations in blocks of code
  • Hiding machine-dependent representations wherever feasible
  • Omitting “eval” or similar metaprogramming constructs
  • No implicit conversions of datatypes during assignment
  • Having immutable storage for everything, allowing referential transparency
  • Disallowing rebinding of variable names
  • Support for pattern-matching and destructuring for arrays and associative arrays and composite types
  • Functional constructs encouraged (map, reduce, recursion) over accumulators and for loops
  • Mandatory TCO wherever possible
  • Native set operations
  • Native support for business-relevant types like dates, times, durations, and time intervals
  • Native support for CSV, XML, and JSON
  • Native support for arbitrary precision math
  • Native support for matrix operations
  • Native support for HTTP

This is a work in progress!

Please direct all questions, comments, concerns, and hatemail to angersock at this domain.

2018-06-26 edit: Such a work in progress, I apparently left typos all over the damned place. >:(


I had a delightful holiday for Christmas and NYE, albeit one mostly spent out-of-town. On the way back home, while using a “luxury coach” (basically what used to be considered first-class on airplanes before they started going to rubbish), I ran into a fellow traveller I recognized from a local university.

This person was working on a language for “non-programmers”, for folks like business users and data scientists—people that they claimed had no formal CS education but who still wanted to use computers to automate their jobs. We chatted for a bit and ended up disagreeing on some of the finer points of language design, but it did get me thinking.

One of my most deep-seated beliefs about our industry is that we spend far too much time reinventing wheels and so actually pursuing the implementation of a language strikes me as a mistake. But, thinking about the features in the language that would be useful is another matter entirely.

So, this post is going to cover some of what I consider to be the most useful features such a language could have and the reasoning that goes into the existence of said features.

Let’s call the language…I don’t know, “schlub”.

The Problemspace of schlub

Schlub is meant to target users that are motivated and technical but who do not actually care about writing programs properly as part of their workflow.

These are users that are smart/stubborn enough to wrestle with bugs but who are not fluent in a given language or who are deliberately not spending time making “nice” code. If a senior software engineer is a master engineer designing Cheyenne Mountain complex, a schlub user is a grunt digging a fighting position—they know what they want, they accept that doing it is going to suck, but they need it now.

Long-term maintenance is not important to a schlub user, thus we don’t worry about affordances for design-by-contract or libraries or software-in-the-large. Schlub users also really don’t care about CS or related topics: if something runs too slowly, their department head cuts a bigger check to AWS and they buy more or larger instances.

Schlub users live in the real world. They care about math, statistics, and engineering, and so the language has a first-class understanding of units of measure, of time, and of dimensional analysis.

Schlub users do care about detecting simple problems (typos, type conversions, etc.) that can be caught at compile time.

Schlub users do care about interop with legacy data formats. So, JSON, XML, HTML, CSV support are all required. Similarly, they do care about HTML documents, because that is a very real usecase.

Schlub’s users do not care about the representation of their data. They don’t care about bitwidths of integers, they don’t care about precision of mantissa, they sure as hell don’t care about textual encodings.

Overview of Schlub

I’m not going to give a BNF grammar or whatever of the language, but just hit some salient points that I want to see.

A lot of this is stuff that in other languages would be addressed in the standard library, or left to the whims of the compiler/VM engineers. However, I think that if we call them out ahead of time it’ll make life a lot simpler.


So, first thing is that the language should look and read mostly like Pascal/Elixir. This is done for two reasons: first, we want a language that isn’t full of curly-braces and things that would frighten off users, and second (and more importantly) we want a language whose syntax encourages the use of single-pass compilation.

We want single-pass compilation mostly to steer us towards “fast” compilation. I’d ideally like such a language to be continually compiled during entry in an IDE, so that users get immediate feedback when they enter something that doesn’t make sense.

It also helps discourage the later growth of the language compiler to support weird optimizations and other stuff.

We’re going to use := for assignment and = for equality testing. Enough is enough.


No macros. If the user is smart/motivated enough to use a macro system, they’re motivated enough to use a real programming language.

This does mean that the language is annoying and maybe error-prone to doing some types of bulk-processing in.

However, usually the time taken to pick the perfect macro to clarify a problem (for most users) is going to outweigh the barbaric copy-and-paste-and-edit solution that 99% of other users will have. It also serves to make implementation of the language simpler as well as giving a minor point towards people having to read (God help them!) legacy schlub code.

Similarly, no user-defined libraries. Libraries encourage the use of (always eventually bad) abstractions and hamper optimization. If it’s something that is common across many projects, it should be part of the language. If it’s just weird business logic, it’s more likely that a) the business logic shouldn’t exist, b) the logic should be contained next to the code that uses it so both can be replaced together, or c) the logic is fiddly enough that replacing it in a library will break other functioning programs.

We include no features for eval or compile or similar run-time source code translation. Sufficiently warped users can do clever things with shelling out.


There are a small set of datatypes in the language. Primitives are thus:

  • Functions (because composing functions has been shown to be absurdly useful and can be understood easily by end users)
  • UTF-8 strings (because strings, and because UTF-8 can subsume legacy ASCII records easily)
  • Dates
  • Timestamps
  • Time intervals
  • N-dimensional matrices of arbitrary precision complex numbers with units (no specific integer or floating-point type, scalar types are just 1x1)

In addition, composite datatypes (arrangements of primitive data or other composite data according to certain rules) afforded are:

  • Ordered lists
  • Unordered sets
  • Associative arrays

Note that the reason we support composite types is that most interesting real-world engineering consists of taking one arrangement of data, gathering it into a form for calculation, and scattering it back out to another form more convenient for the next business process/consumer.

Any language not giving affordances for that use case is doomed. Any language that offer interop (as Schlub does) with nested hairy data trees (XML, JSON) is doomed.

A note about typing

Since we support maps and arrays and nesting and first-class functions but also do not support user-defined types, we can’t really be statically typed in any useful sense.

We can however be strongly typed and complain loudly if users try to assign a number to a string, or a map to an array, or whatever else.

A note about storage

All data in schlub is immutable and has referential transparency. This solves a great many issues for automatic generation of concurrent code, and also simplifies the mental model most schlub users have. Schlub does not support rebinding of variable names within the same function scope.


Math operations in Schlub are geared more towards something a user of Fortran, Matlab, or R would be familiar with.


All numbers are n-dimensional matrices of complex numbers internally. For the convenience of users, scalar values can be written without using matrix notation (the compiler can take care of that for them).

It’s annoying having a language that has no support for complex numbers (looking at you, JS), or that has weird and shoddy support for them (hi C). Even if the vast majority of cases does not require it, when doing some types of math (or signal processing, or other stuff) it is quite necessary.

A note on representation of numbers

The reason for hiding the machine representation of the numbers from the users is that that is almost always done to do clever bit-twiddling hacks (outside the scope fo the language) or to constrain what users can accomplish by making them aware of the limitations of the machine they’re running on.

Clearly, though, we can’t have users losing their minds (and cycles!) over storing numbers with great precision where it really doesn’t matter. Similarly, there is no hope of doing proper optimization and making use of hardware correctly if there is no way of saying “okay, this fits in 32 bits, go do the needful”.

The approach that schlub takes to solving this problem is to instead require the user to specify the precision of mathematical operations they desire (in terms of either significant figures or decimal precision. This allows a sufficiently advanced compiler (haaaah) to select the most efficient representation and operations for implementing a given operation, as well as offering up the opportunity to give schlub users basic information about the precision of their calculations.

This would also perhaps help curb the troubling tendency of people to go and trust blindly long strings of digits that give a false sense of quality of calculations—but that’s perhaps just optimism on my part!

Functional programming in schlub

Things like for-loops are holdovers from having to manually increment pointers, and since we don’t expose pointers we don’t expose for-loops.

Additionally, for the layperson instructions like “eat everything on the table” (in Javascript, something like table.everything().map(eat)) or “slice every fruit on the table” (table.everything().filter(isOrange).map(slice)) make quite a bit of sense if explained in terms of sets of things and operations on those sets.

So, schlub supports the usual things like map, reduce, filter, and functions-as-arguments. We also support the extremely useful idea of sets and set operations, so things like unions and intersections (commonly used) and cartesian products.

The other nice thing is that, by using functional constructs, we allow the user to instrument their programs in such a way as to allow easy scaling for certain types of tasks. If a thing runs very slowly, forking things off into different threads (or machines, in a hosted environment!) as part of the internals of a map or reduce call seems quite attractive.

Weak points and existential problems with schlub

As fun as this is, there are a few issues that I see with the language.

First, if the standard library and language is not continuously updated, it loses its usefulness. Or, worse still, users create transpilers to convert their favorite dialect of Schlub into canonical schlub (adding things like, say, libraries). This kills the portability of Schlub.

Second, the target audience for this language might not actually exist. The folks that need to do those sorts of operations probably already have basic proficiency in Numpy (or perl, or tcl, or R) and lack the desire to switch.

Third, the approach to software writing might be too pessimistic. Maybe requiring copy-and-pasting of code for each iteration of a project is actually a bad idea. Maybe maintenance and software-in-the-large is actually a valid concern.

Fourth, schlub is meant to write basic transform programs, or to do batch processing. Writing a GUI in it would be miserable, writing a compiler excruciating. There are problem domains like this that schlub is awful at (by design), and I don’t know if those domains are actually as important as I think they are.

Fifth, the wink-and-nod of schlub is that, behind the scenes, our focus on business things and not on CS/SE-relevant things (say, by hiding the machine representation of numbers or by requiring a particular form of FP) is rewarded by letting us do clever optimizations and automagical distribution of tasks and things. It is extremely naive to assume that that bet actually pays off—“sufficiently-advanced compilers” are almost always a pipe dream.

In spite of these issues, I still think the concept is an interesting one, and I’d appreciate email feedback from folks who’d like to spitball with me on it.

The Friendlysock Experiment, Subjective Results

I’ve been putting off writing about this for a while now, mostly so I could digest my opinions on the whole thing and try to fashion something useful to others.

In order to help respect my readers’ time, I’ll give the experiment and subjective results up front, and then give longer (and quite a bit more rambling) commentary afterwards in case people are curious.

(I, of course, think the interesting stuff is the process and not so much the results, but maybe you don’t.)

Note that all of this is in the context of the Lobsters (and, to a lesser-extent, HN) aggregation site.

The experiment, short version

From 2017-06-08 to 2017-07-08, I undertook the Friendlysock experiment.

Described in my profile as “only positive posts”, I did my best to change my posting behavior to:

  • …avoid calling other users names or trolling
  • …avoid non-constructive criticism of others’ work or submissions
  • …actively find something positive to say about even the most troublesome submissions
  • …be as polite as possible in my meta commentary and advice (posts about tagging, submissions, voting, etc.)

The subjective results, short version

Observed effects on my posting style:

  • I was still able to reply to anything I felt the urge to—I wasn’t hamstrung.
  • Some comments were harder to write in a positive tone, and required additional thinking.
  • I found myself getting more annoyed at the negative posts of others, significantly so.
  • I used more emoticons (smileys!) than usual in an attempt to prevent misunderstanding.
  • Most times when I felt the need to point out that somebody was wrong I ended up taking a politely confused tone (“I’m not sure that I understand thus-and-such” instead of “thus-and-such is a really bad idea”).

Observed effects on interactions with other users:

  • A few people actually messaged me and wanted to know what was happening.
  • A few people commented on me being nicer in tone in threads.
  • Fewer direct replies were aggressive in tone, and in general were more polite.
  • People on IRC were confused that I hadn’t carried over the experiment there.
  • I still was routinely downvoted as “troll”.

Future work, short version

This is just my subjective experience. A better, more quantitative conclusion could be drawn if I had:

  • Text bodies of my posts for sentiment analysis
  • Sentiment analysis of replies to my posts
  • Breakdown of upvotes and downvotes by category
  • Number of child comments for posts
  • Count of my own posts

These figures for the month of the experiment, the preceding three months, six months, year, and time to date should be enough to establish a nice baseline and see if my intuitions are correct. I’ll have to ask @pushcx really nicely and maybe they’ll help me out.

If I get this information, I can do a nice write-up “The Friendlysock Experiment, objective results”. :)

The experiment, long version

Diversions in SEO

Every so often I Google my username, just to see what will pop up. This is handy because I like to know what people will think about me after a casual search if they haven’t seen my work before.

About a year or two ago, I’d gotten annoyed at some punk kid wanting to reinvent metadata filesystems—and because they were so hyperbolic in their writing, I acted by near reflex and cut them the fuck down. Angersock 1, punk kid 0, great success, maybe they’ll go on and spend their time on something useful instead (like getting laid, porting C stdlib to Rust, or something).

They apparently had read my posts and were shocked and provoked by my comments.

Reading through their words, my internal monologue went something like this:

(…) Yeah, this particularly vehement dismissal pissed me off too. Even if it’s not me or the LTP guy, I hope someone can prove him wrong.

That’s right, buddy, angersock has set the bar—

I want to respond to this but I don’t know how.

—and it looks like you aren’t up to the task, so maybe you—

I hope I never become this jaded.

—huh. Well, shit.

This punk had read me loud and clear, shots had landed exactly where I’d wanted them to, and yet I was getting the feeling that the sheer earnestness of their efforts meant that maybe I’d done something wrong, had maybe stepped on a weird little flower that just wanted to grow into a big happy weird flower.

Sure, trolling people is fun and needling well-meaning idiots is probably the fastest way to get them to reconsider their choices, but I couldn’t shake Vonnegut’s advice.

And then I read the other post they had on the topic and had linked to, and it looked like sure enough they had spent a few days thinking on what I’d said and had managed to pull the wisdom (because you always need to include some) from the bile:

So I’d like to thank angersock for this series of comments, even though an earlier one was a bit harshly worded.

Well, this one is pretty harsh too but it’s completely reasonable too.

My heart warmed a little, as it looked like the person had taken my gruffness and adjusted course, and were going to do some cool things with a little less naivety. They weren’t a punk at all.

But, it could have gone the other way. They could’ve been reading it after a bad day at school or work, after their dinner had gotten burned, after their phone screen had gotten cracked in their pocket…it could’ve been the final straw and had caused them to give up on their project all together.

That wouldn’t have been cool. And it would’ve been my fault.

It could’ve been better, right? I could’ve said something that they thought was overwhelmingly constructive and thanked me in errata or something. But I hadn’t.

Around the same time period, @brucem from the #lobsters IRC channel had been expressing that they’d found my posts overly angry and negative, and had hinted that maybe I should reconsider how much scorn and annoyance I was broadcasting. I value the voice of my writing, and the headspace that often accompanies it, and so I filed this tidbit away and continued on my merry course.

@brucem, being the wise and patient person that they are, continued (and continues!) to be a wonderful human being to converse with—their advice and admonishment simmering in the back of my head. They could’ve just as easily thrown me into a killfile.

A late-night revelation in a strange place

Fast forward to June of 2017.

There’s been a death in the family. Nothing unexpected and nobody immediate enough that I’m distraught but still I’m in a somber and contemplative mood.

I’m in a hotel room in an unfamiliar part of an unfamiliar state and am trying to get to sleep by tiring myself out browsing Lobsters (as one does). I get the urge to Google my username.

I run into this tweet almost immediately. It’s @aphyr (yes, that aphyr) using a screencap out of context to suggest I shouldn’t be on Lobsters.

Were it anyone else, I’d laugh and ignore the sour grapes.



@aphyr is somebody whose work I really respect and with whom I haven’t been arguing and spatting for years.

@aphyr has written some genuinely beautiful things, as well as some of the best interview satire I’ve had the pleasure to read. This is all in addition to their utterly brilliant work on distributed systems testing.

Discovering that the fourth or fifth entry when searching my username is that post, I got to thinking a bit. That, the day’s events at the funeral, the half-remembered interactions with that filesystem poster, comments by folks in IRC…

I believe in Maxim Sixteen, but was this how I wanted to be remembered?

Just some grumpy crank troll on the internet?

A one-trick pony

And I wish I could claim that that reflection alone was enough to spur me to action. Such a narrative is tidy, and neat, and paints me in a slightly sympathetic light. It is also wrong.

The fact is, people become known by their writing styles and content. We have one user on the site who is consistently long-winded in almost every single post they make, to the extent that some have created scripts to automatically hide their words. We have another user that near-uniformly writes with bad grammar and perpetually positively. Still another is known for their reliable injection of historical technology lessons into every available post.

Whenever I encounter those users, I know what I’m in for. There is not much novelty—which is fine—in their content. And I bet that other users treat them the same way.

I was concerned that my writing was becoming a bit redundant. I was worried that I was getting a shtick, and that that shtick was coming to define me in the eyes of others and, worse, was making me intellectually lazy and creatively bankrupt.

There’s no art to what had become my signature style. There’s no craft when most of the posts that involved disagreements had become mechanical—express wonderment at some point with which i disagreed, make a joke, avoid direct personal attacks, pick on logical inconsistencies or overstatements, use suitable examples from history with links, close with a joke or insinuation of ignorance. On the rare occasion when I was absolutely and obviously wrong, politely cede the point.

Arguing with most people online is like starting a bloody-knuckles tournament in a ward of hemophiliacs: yes, you’ll win, and yes, you’ll look like an asshole while doing so.

So, it was time to change.

Disorganized subjective observation about being friendlysock

(This next bit is a mixture of things I recall from the experiment and things I’ve thought about and internalized since then. I may claim some things about my posting that aren’t strictly accurate—consider this more of a normative than historical section, concerned more with what ought to have been than what always was.)

One of the big things I noticed was that breaking old habits was hard. Lots of comments needed to be reread and reworded before I put them up. It’s really hard to uproot and neuter a deeply-seated sardonic response style back to mere sarcasm and then to something positive that is worth posting.

I started trying to follow the “Yes, and” mindset. In improv or extemporaneous speaking, this is a technique whereby one does not contradict what somebody else has said but instead builds upon it. It’s polite, it usually triggers further discussion, and it doesn’t leave the person you’re replying to feeling put-down.

One of the other things I tried doing was to ask more questions. Even if I really thought somebody was full of shit, misguided, or incorrect, I figured that it was better to ask politely than to disagree bluntly or to link clearly contradictory information.

Another thing, more a result of talking with @pushcx than anything else, is trying to catch myself being inadvertently dismissive. Because reasons, it’s much easier for me to assume a particular worldview or use-case and just plain gloss over how other people’s perspectives and cut straight to the discussion.

It’s fine to do that deliberately—it’s hard to communicate if we’re always covering every angle, and it’s hard to talk about some things if you can’t dismiss conflicting realities—but doing it by accident is sloppy and a recipe for hurting people and getting blind-sided.

I also tried to occasionally just say more nice things to users, even when they did irksome things like misuse tags, post marketing spam, post news, or whatever else.

I’d write things like “Hey, that’s a really neat article you have, but it isn’t so focused on tech—I think they’d appreciate it over at” and people would almost always thank me and stop doing the irksome thing.

One of the other rather odd things I noticed was that, as I started putting those principles into practice, I became sensitive to posts by other users that didn’t follow these practices.

I found myself keying off immediately on people being overly negative or starting a reply off with some kind of grumpiness or just plain being impolite. Part of me wondered (wonders?) if that’s how folks read my own work.

Where this leaves me

I have a few beliefs about writing and engaging in good-faith discussion online:

You have to write competently and clearly. You have to avoid ad hominems, to avoid petty insults. You have to use facts, reasoning, rhetoric—you must be friends with the real and strangers with the convenient. You cannot invoke shibboleths accidentally, you cannot speak from a position of privilege unintentionally. You must always show your work.

You must write your honest opinion, unflinchingly and without reserve, and if your authenticity confuses and confounds some it will gain that much more purchase among those who recognize it for what it is.

And that’s all really important to me. But it’s not enough.

For those of us that, like me, spend a lot of time online, it’s really too easy to just get a constant stream of garbage flowing through our information digestive tracts. It’s too easy to get in a headspace where any remotely positive feedback is some goddamn carebear coddling somebody.

It’s too easy to get accustomed to reading negative and hateful things, and even though we can (and I have!) go back and forth about how a degree of toxicity is helpful for preventing blooms of stupidity, the fact is that that toxicity arises pretty much unbidden. We don’t need to purposefully cultivate it.

I’ve spent the time being positive, after a long time being negative. I’ve enjoyed the minor challenge of breaking out of my old patterns, and I think that the new patterns are probably worth keeping.

So, I think it’s time to retire angersock for now, at least on the Lobsters site.

And no, that won’t make me any less grumpy. It won’t lead to the deletion of nastygrams and tirades of years past. It certainly won’t mean that a bunch of people whom I’ve alienated (or who have, in the manner of the times, become outraged and alienated themselves) will forgive me or decide to come back into the fold.

But, maybe, it’ll make sharing a message board with me a little easier. And, maybe, it’ll help set an example for people to be nicer to each other and to have better conversations.

That’s why we’re here, right?

Hedging Bets


This is a fun little thought-experiment. I’m not detailing anything our friends in finance and business don’t already know, but it might be something entertaining to chew on if you are (as I am at this moment) stuck on a bus and needing something to do.

A system for gambling

My mother had a rule for gambling, passed down through her family:

When you go into the casino, put the money you’re betting in your left pocket. Whenever you win, put the winnings in the right pocket. You can keep gambling as long as you have money in either pocket. Once your pockets are empty—you stop.

The intent of this system is to:

  • Prevent the mixture of winnings with principal.
  • Give the option of “reinvesting” winnings.
  • Most importantly, to place a hard limit on losses.

So, why do we care about this?

A worldwide casino

Let’s play with this system and see if we can get any insights for larger-scale gambling.

The game we play is simple. The player state is:

  • D0 the initial liquid funding of the player.
  • D the amount of liquid funds available.
  • N the number of tickets a player owns.

The game state is:

  • T the time elapsed in the game since the start time, T_0.
  • P_ticket the current purchase/selling price of a ticket.

The rules are:

  • Tickets are completely fungible—you can buy fractional tickets.
  • Every time period dt, you can buy zero or more tickets at price P_ticket(T), up until you’ve exceeded D. Each purchase is deducted from D.
  • Every time period dt, you can sell zero or more tickets at price P_ticket(T), until you’ve exceeded N. Each sale is credited to D.
  • Every time period dt, P_ticket will monotonically increase by some amount.
  • At some time T_ohshit, P_ticket will begin plummeting.

The goal conditions:

  • You win if you walk away with more money than you started with.
  • You lose if you walk away with less money than you started with.
  • You draw if you walk away with the same amount of money you started with.

Trivial strategies: not playing

So, the simplest strategy is to not play at all. Take the funds and walk.

This prevents any possible lose conditions, but similarly prevents a win. A draw is assured.

Alternately, immediately buy all of the shares possible (floor(D0/P_ticket)) and sell them on the subsequent timestep.

Unless T_ohshit is happens at T=dt, you’re guaranteed a neglible profit.

Stupid strategy: Ride the wave

The strategy

Until T_ohshit, you know that buying a ticket will only get more expensive than at T_0. Thus, it makes sense that the cheapest time to buy a ticket is at the very beginning, so you should do that.

Now, the best time to sell is going to be at T_ohshit—but you won’t know that time has come until T_ohshit + dt. At which point, since the price is plummeting, you know the best time to sell is as soon as possible.

So, you say “Aha angersock, I will buy at the first timestep and sell at the moment I think T_ohshit has passed.”

Analysis of the payout

The profit is going to be equal to the revenue of the tickets sold less the cost of the tickets purchased.

In our case, that is:

Profit = Revenue - Cost

We can expand that out:

Profit = ( N * P_ticket( T_ohshit + dt ) ) - ( P_ticket(0) * N )
Profit = N * ( P_ticket( T_ohshit + dt) - P_ticket(0) )

Now, given that we purchased all of our tickets at the beginning, we know N:

N = D / P_ticket(0)

And so:

Profit = D / P_ticket(0) * (P_ticket( T_ohshit + dt ) - P_ticket( 0 ) )
Profit = D * ( 1 - P_ticket( T_ohshit + dt ) / P_ticket(0))

Not super impressive, but it reassures us that rudimentary microeconmics still works. Note though that the profit is directly dependent on the amount of funds spent in the beginning!

Flaws and assumptions

There are some problems with this, in practice:

  • What if my cat eats my router and I don’t catch the timestep directly after the crash? How long do I have before I’m not longer profiting?

  • What if the ticket price changes really drastically in like one time step?


That’s it for now. Next time we’ll:

  • See what more conservative strategies we can play
  • See how to bound the risk of missing the T_ohshit event.
  • See if we can adapt to a removal of the monotonically increasing and decreasing assumptions.

It Could’ve Been Awesome, but Now It Sucks.

A fellow contractor, who had been functioning as effectively architect and back-end lead for a company that had also hired me for a while, said this one day in our back-channel.

Long story short, the business folks had an interesting problem, a potentially profitable business, and were doing pretty much everything they could think of to steal defeat from the jaws of victory.

It struck a chord with me, and perhaps it will with you: how many projects have we all worked on that could’ve been awesome, but then sucked?

Too many, in my experience. Too many.

Unreferenced Function Parameters and You

What is an URFP?

Oftentimes it is useful to declare a function to match a particular signature but without making use of the parameters it consumes. Inevitably, this causes a bunch of griping from static analysis tools and compilers.

A short example, urfp.c:

void foo( int bar ) {

int main (int argc, char** argv) {
    return 0;

And when we feed it to gcc, we get:

angersock@devbox:~$ gcc urfp.c  -Wunused-parameter
urfp.c: In function foo:
urfp.c:1:15: warning: unused parameter bar [-Wunused-parameter]
 void foo( int bar ) {
urfp.c: In function main:
fp.c:5:15: warning: unused parameter argc [-Wunused-parameter]
 int main( int argc, char** argv) {
urfp.c:5:28: warning: unused parameter argv [-Wunused-parameter]
 int main( int argc, char** argv) {

Why does this happen—other than the compiler flag, I mean?

Most frequently in some kind of OOP language we find ourselves overriding a method on a class. That override may not use all of the arguments supplied by the caller: for example, a stub update( float dt) method in a game entity’s logic.

Fixing URFP In C/C++

So, to fix this, we define a simple macro:

#define URFP(x) ((void)x)

Then, we just use it at the top of a function to shut up the compiler.

void foo( int bar ) {

int main( int argc, char** argv) {
    return 0;

Note that in C++ this isn’t always safe, because of type overloading. One can imagine a situation wherein some clever person has overridden the void typecast operator on their class, and so when you URFP it away it still does something unseemly instead of disappearing. This is a failure of the C++ language.

In Javascript

JSHint and JSLint will both complain to you if you don’t disable the behavior.

In JSHint, the appropriate line to use can be found in the docs:

"unused" : "strict"  // Unused variables:
                     //   true     : all variables, last function parameter
                     //   "vars"   : all variables only
                     //   "strict" : all variables, all function parameters

I tend to always leave this at strict, because I prefer to get any help from the linter that I can.

The problem is, of course, that this will make the linter scream bloody murder whenever you run it over your source code. So, a moral equivalent to the URFP above is:

function URFP( x ) { /* jshint expr:true */ x; }

This will let you consume the variable in the function and do nothing, and then the jshint expr directive will keep the linter from complaining about the lack of invocation or assignment.

HN/Lobsters: Good News, Bad News, How to Win Big (Part 3)

In part 1, we talked about HN/Lobsters-style sites and how their karma mechanics promoted good behavior and helped produce civility and discussion.

In part 2, we talked about how the same mechanisms could be gamed in ways that tended to corrupt and make those communities toxic.

In this final part, I’ll go over some strategies that I think can help mitigate these problems.

How to Win Big

Order posts randomly

One of the consistent themes from the previous section involves fiddling with the post order in order to get more upvotes. Even with several posts of isomorphic content, the first post will probably get more upvotes than the others.

So, in order to remove the entire category of “Hey, let’s play with the ordering of posts and reply to things that otherwise aren’t related”, sites should just display subthreads in randomized order. This would mean:

  • All child posts of a subthread at the same level should be displayed in random order.
  • Randomization shouldn’t occur per-pageload, because that’d be slow.
  • Randomization should occur per-user, so the same user can rapidly find things.

This does perhaps mean that bad posts show up at the top of the page, but that isn’t guaranteed to happen. An option for omitting posts below a certain threshold (say, 0 karma) might also solve this, but that introduces secondary effects that might be bad.

Throttle story submissions

In order to prevent spamming of the front page with little easy-upvote and click-bait stories, prevent users from submitting more than one or two stories over the course of some time interval. This also:

  • Prevents a handful of users from dominating the front page through sheer quantity.
  • Prevents users from being overloaded by constant churn of submissions and allows proper
  • Slows the effects of bad submissions (even if bad ones get in, it is at a slower rate so damage isn’t as acute).

Aggressively and transparently moderate your community

HN already does this, though the transparency is lacking. Lobsters is completely open about all moderation actions, and has a public log of what has occurred.

Aggressive moderation is not necessarily harsh moderation, but instead refers to admins and sysops keeping a close eye on the community and forums and making sure that bad actors are dealt with quickly. This means:

  • Identifying and dealing with abusive behavior.
  • Proactively organizing tags and titles for consistency.
  • Reminding users of community decorum as needed.

Moderation should never, though, exhibit the following behavior:

  • Editing user posts without explicit permission
  • Banning users with dissenting opinions but who are civil.
  • Removing stories or comments preemptively (censorship)

Note that there is seeming conflict here: how can a moderator both protect the community against abuse and also avoid censorship? That is the reason that frequent and close (aggressive) moderation is so important: done correctly, it allows the community to build up a set of standards and hold to them, and thus they learn to self-regulate to an extent.

Moderation is ultimately dependent on community cooperation and focus, and as long as the community hasn’t normalized into its culture abusive or disruptive behavior or submission strategies (as talked about in the previous article), then moderation itself can be done without devolving into strong-arming.


That’s it for this series. At this time, I don’t really feel like I’ve got better advice, and frankly I think I’m done writing about this topic for now. I’ll update this article as ideas occur to me later. Thanks for reading!

HN/Lobsters: Good News, Bad News, How to Win Big (Part 2)

In part 1, we talked about HN/Lobsters-style sites and how their karma mechanics promoted good behavior and helped produce civility and discussion.

Next, we’re going to cover how those same mechanics promote toxic behavior, and how a bad-faith poster can cynically exploit the system in order to gain standing.

Note that this is all going to be behavior accomplished by a normal user. No sockpuppeting, upvote ringing, or anything else sketchy needs be happening—this is just playing the game straight with a different value perspective. As such, this is also all behavior that plausibly a normal user may accidentally engage in.

Bad News

We’ve shown how to be a good poster, and how to really improve the community and get decent amounts of karma for little time investment.

Let’s assume though, in typical paperclip-making machine fashion, that we only care about increasing our karma. This assumption also means that we have extra time (perhaps a couple of hours a day) to spend…that being the case, every little trick we can use will help ratchet us to greatness.

The bad news is that there are people on HN and Lobsters that are like this and that, worse still, the same mechanisms that make normal posters good make bad posters really really toxic. These toxic posters take advantage of at least some of the following anti-patterns:

  • Strategic shitposting

  • Junk submissions

  • Post order manipulation

  • Post manipulation

Strategic shitposting

Strategic shitposting is a catch-all for purposefully making posts that gain karma without contributing to the discussion. Examples of such posts would be some of my earlier work on Hacker News. This behavior relies on throwaway jokes or snarky replies to comments, almost always able to produce a few more upvotes than downvotes. Properly formatted (in my case, leaving out all punctuation and capitalization to make it easier to parse as less thought-out than my normal work) these posts somehow manage to amuse more than they annoy, and in so doing they can reap a tidy profit.

The posts in question always need at least a little relevance, in order to prevent flagging (Lobsters) or downvoting (HN), but their main purpose is to get a visceral reaction (typically, humor and amusement) in the reader. Once that reaction occurs, they’ll probably get an upvote.

How does this work? Let’s talk about voting.

How voting works on HN/L sites

Why do people upvote things?

  • They just want to click on the little arrow.
  • They agree with the point the author is making.
  • They disagree with the point the author is making, but agree with the writeup of the point.
  • They want to reward everybody who has participated in a thread of conversation.
  • They want to manipulate the rankings (more on this later).
  • They assume that whatever the person is saying is correct (patio11, tptacek, pg) and want to reward them.
  • They want to downvote, but they missed on the touch interface. HN won’t let you correct a mistaken vote, though Lobsters will.
  • They want to reward the poster whenever possible.

Why do people downvote?

  • They disagree with the point made by the post (primarily HN, due to a misguided public policy statement by Paul Graham and parroted thereafter).
  • They believe the post is rude or uncivil (formerly on HN, now primarily Lobsters).
  • They want to pile on downvotes for already downvoted things (any posts that are greyed out tend to mark themselves as “downvote me”).
  • They meant to upvote, but missed on the interface (again, mainly an HN problem).
  • They want to manipulate the rankings (more on this later).
  • They want to punish the poster whenever possible.

In Hacker News, for a long time, downvoting was de facto reserved for marking comments as excessively hostile or rude or off-topic. Lobsters to this day tends to function that way and even has a more nuanced downvote system for showing why a given post was downvoted.

Using voting mechanisms to profitably shitpost

This standard means that—for a poster without a reputation, and for a post which is otherwise not abrasive—if a post gets any reaction, it’ll probably be an upvote. Thus, the winning shitposting strategy is to write posts that can cause a strong reaction without being too difficult to write. A few different types of posts have enhanced survival characteristics by leveraging that truth:

  • Posts that are primarily jokes, using the context of discussion as source material.

  • Posts that signal simple agreement with whatever the current zeitgeist of discussion is. They need not be long, but people react more strongly and much more positively to these than short disagreeing posts (which they may even downvote!).

  • Posts that are minor corrections (technically correct, the best kind of correct). The reaction is due to the thought process of the reader checking that the post is in fact correct, rewarding the correctness, and moving on, even though the post itself contributes little to the conversation. Think grammar or URL corrections.

  • Lampshaded off-topic rants that are tangentially related. Most HN/Lobsters readers seem to forgive a blatantly off-topic post if it contains an upfront admission that they are so.

  • Griping about injustice or outrage, the more entrenched the better. Pandering to injustice and impotent outrage evokes strong reactions and such posts can be easily tailored to match the overall views of the hivemind.

None of these posts actually tend to elevate the discussion or reveal new truths, but people will almost always upvote them more than they downvote them.

And that’s the source of their toxicity: shitposts do at least as well as quality posts, they don’t increase the signal of the community’s nominal area of discussion, and they are very easy to crank out even by idiots.

Junk submissions

Junk submissions are articles and stories that do well in karma but that again dilute the focus of the community. I suggest that the voting patterns for submissions mostly follow those mentioned above for normal posts and comments, so I won’t rehash that here.

To pick a good junk submission, you basically want something that:

  1. Doesn’t require an in-depth understanding of the subject matter to comment on. Some random user who sees an article on type algebras statistically isn’t going to be in the population who cares about such things, whereas bike-shedding on some Algol-derived language is fun for the whole family.

  2. Doesn’t take a long time to read, because people will be less likely to upvote it. The longer somebody takes to read an article, the more likely they are to move on to something else (or to disagree with it, or ignore it entirely). This is precisely the opposite behavior from giving your submission upvotes.

  3. Evokes a strong reaction in the reader. As with comments, the only bad reaction from a user is no reaction—so, pick a topic that demands to be felt strongly about. So, “C is Dead” is going to be a better article than “Subtle memory aliasing issues with legacy C99 code”. Similarly, “How We Prioritized Diversity” is going to do better than “Surveys of Hiring Practices and Diversity” or mundane bureau of labor reports, even though it may have objective information.

  4. Is likely to create a lot of discussion. Remember, the ranking algos slightly favor more discussion over less discussion. You want to pick an article that is hilariously one-sided, or that leaves out key details so as to provide speculation. Anything that is cut-and-dried is probably not going to get a lot of comments compared with proper bait.

In other words, you want news, gossip, and/or controversy. HN and Lobsters both have some measures in place to lower submissions that have a lot of discussion but few upvotes, but those aren’t always effective. Additionally, done properly, you can use a junk submission to create a loud discussion and then profit off your own posts and comments within that discussion even if the story itself gets torpedoed. Loud arguments may take several days to slide both off the front page and out of people’s minds.

Gossip is attractive but obvious

Gossip tends to get shut down on HN, mostly because the best gossip in our industry tends to run counter to the explicit goals and interests of the folks at Hacker News. They understand that frequently appearing as a clearinghouse for muckraking damages their reputation and their community, so mods will kill off stories that are primarily gossip.

Gossip about the community site itself (meta as it is known in other contexts like Stack Overflow) trips the same breakers. On the useful side, though, meta discussion easily hits all of the 4 criteria for a junk submission, least of all because it usually creates a lot of discussion and everyone has something to say.

Controversy is a reliable standby but self-limiting

Controversy is often overlooked by users as needing to be curtailed, but may fall prey to overzealous moderation. The same thing that causes people to upvote controversial articles tends to make them complete jerks in the threads, and rapidly the civility of such discussions tends to die out. Pre-emptively, mods may hide or nuke such threads to prevent them from dominating the front-page. While the articles rage on, though, you can expect a lot of votes—especially if you picked a submission that doesn’t blatantly appear to be using this tactic. It can often help to seed the discussion with a comment to highlight or bring out the controversy, and in so doing get better mileage out of a safer article that doesn’t at first glance appear incendiary.

As of the time of this writing, the most reliable form of outrage submission invokes social justice. Everybody on HN or Lobsters has known somebody who has been discriminated against unfairly, because we really do have a history of that in our industry. It’s a topic getting a lot of coverage in other sectors.

(Aside: I don’t mean to use social justice as a pejorative here: it’s a term I’ve seen used by both sides a great deal at this point, and it tends to be a good shorthand for the category of discussions of privilege, diversity, gender, equity, and similar issues. I think those issues are important to examine, but here we are only concerned with their utility for gaining karma.)

Let’s look at it under our four criteria:

  1. Social justice outrage is typically reported in either news or blog form. There is a large (and often impenetrable to the untrained novice) body of academic work on social justice concepts, but the majority of what is discussed online today is short-form and written to make people aware. Similarly, everyone has a least some opinion on the topic, even if it is as simple as “I hate political correctness!”.

  2. Social justice outrage often is event-based, using social media. Because a lot of material is sourced from Twitter or Medium, it tends to be pretty short and quickly-digestible. You don’t have to grep through more than a few tweets of content to get the meat of many posts.

  3. Social justice outrage lends itself exceptionally well to provoking a response. Because of the previously-mentioned history of discrimination in tech, and because everyone has felt excluded or slighted at one point or another, any user with any shred of decency or empathy will find some resonance with any material involving those topics. Additionally, there are people who are angered or feel persecuted whenever social justice articles show up—and they tend to either upvote an article to get it discussed or downvote so conspicuously as to garner sympathy upvotes from users not sharing their preferences.

  4. Social justice outrage always results in lots of discussion. Discussions on these articles tend to involve a lot of personal suffering (in which case people commiserate, question, or express sympathy) and argument (because people tend to hotly debate facts or deeply-held convictions). Even though the discussions themselves typically don’t enrich anybody’s life, they do generate a lot of opportunities for either quality commenting or shitposting.

All the same, a problem with these sorts of submissions is that are usually heavily moderated once the site admins catch on. HN, for example, seems to heavily monitor and remove these sorts of submissions once they pop up. The counter to this, of course, is to start with articles that aren’t directly about this, and slowly ease in more and more inflammatory social justice articles as the community standards normalize in that direction.

News articles are your secret weapon

News articles tend to be best form of junk submission.

What makes them so great? They map directly onto the four useful traits we talked about above:

  1. News articles are, by construction, easy to digest. To gain the widest-possible circulation and reach, news writing tends to be simple and accessible. For our purposes, that’s perfect.

  2. News articles are almost always relatively short. It’s hard to keep the TechCrunch pipeline flowing if every article is suitable for print in The New Yorker. It is also harder to keep on the bleeding edge if you post long analyses, and frankly it’s hard work. So, shorter articles with links to sponsors and relevant information carry the day.

  3. News articles are, by definition, novel. In addition to whatever feelings the articles promote, news always have a sense of novelty and discovery to them. Almost any user gets a mild rush from not having missed out when reading an article or by having their curiosity rewarded.

  4. News articles tend to create discussion. Everybody loves to show off their grasp of the nuances of a news story that others may lack, and they’ll happily chat about that. Or, they’ll complain about the rest of the story being left out. Either way, they’ll be talking.

There is a deeper toxicity to news, though, and one that only Lobsters so far even seems to acknowledge (through its tagging system):

Every time you post a news article, product announcement, or current events thing, you are creating a minor data point that says that the novelty of the article, and not the content of the article itself, is acceptable for the community. This is an important precedent to set, because it means that as you have a harder and harder time finding good submissions, you can fall back on novelty over quality.

Over time, this means that the front page (say, of HN) becomes filled with things that would otherwise be considered off-topic, including advertising and product releases and whatnot. This is not postulation—this has happened on HN.

On a site like Lobsters, this process absolutely destroys the uniqueness and educational value of the site.

Additionally, as this rot sets in, there is no going back—once the name of the game is “What is the most novel thing we can post?”, only news articles will be commonly successful. They have an entire industry of people behind them optimizing them for that niche, and simple links to other things have little chance.

Post order manipulation

By carefully upvoting and downvoting, as well as picking what you reply to, you can also improve your odds of getting karma.

Observations about how people read posts:

  • Early posts tend to get the most reactions, and stay wherever they’re ranked.

  • People tend to pay attention most to the top-most posts.

  • People tend to pay the next-most attention to the bottom posts, especially in long threads.

  • People skim over subthreads which are more than a couple of levels deep.

  • People may downvote entire subthreads if it turns into one or two posters bickering.

  • People notice early-on if the same poster is replying in all of the subthreads.

These observations suggest some tactics.

  • If a post is near the top of a thread and the thread is long, it is better to reply to that post than to create one at a sibling level. If yours is the only reply to a post at the top, you’ve basically assured your spot as the second post people encounter.

  • If a post is near the bottom of a thread, reply to it. This is again prime real-estate, and bottom posts tend to be blatantly bad—thus, a reply correcting them or mocking them tends to get additionally upvotes.

  • Don’t engage in pointless back-and-forth with another poster. Watch your per-post karma if available, as in Lobsters) and stop once you only are getting a vote or two per reply.

  • Early on, any post that isn’t yours that people agree with should be downvoted if it looks “strong”. Alternately, you should upvote a strong post and reply to it immediately, to help ensure a good spot in the reading order.

  • Resist the urge to reply to everything in a thread. Done too much, or too frequently, you will antagonize the other posters, and eventually they’ll downvote you on principal everywhere in a thread.

The reason that this behavior can be toxic to a community is that while it can help people act more civilly (as in the cases of avoiding back-and-forth and posting everywhere), the behavior itself can cause neglect of middle-quality and late posts. Rankings of posts also become suspect, because a post that is at the top may have only gotten there by the author downvoting more relevant posts and discussion baiting. Subthreads can also become cluttered up by virtue of people using the “post to a top thread” heuristic instead of the expected “engage with posts worth engaging with” metric.

Post Manipulation

Manipulating and editing your posts after the fact is an old technique, but still sometimes productive.

One thing to do is to edit posts for content after seeing a similar post get eviscerated. For example, one may tone down a post from being too aggressive after watching a somebody else get downvoted.

Another reason to edit posts is to remove content that others are using to call you out. This is doubly effective if a replying poster gets really agitated—if you remove inflammatory content after somebody has replied in kind, it appears to the outside observer that that the reply post is being overly mean.

Finally, and perhaps even in decent faith, editing to append additional context or corrections and acknowledgements to a post that was originally incorrect or poorly worded can actually result in more karma. People who may otherwise have been annoyed may say “Aha! They’ve corrected themselves and owned up to it—I shall reward this with an upvote (or perhaps remove a flagging).”)

This is toxic behavior because it tends to destroy the archival value of discussions—for this reason (I assume) Lobsters and Hacker News both disable editing of past posts. That said, if people delete old posts they can achieve similar outcomes. Additionally, it can be really gnarly when people are trying to follow a conversation or point and suddenly the original words that led to a disagreement are gone or are different from what they used to be.

Thoughts on negative strategies

Frankly, these strategies range from annoying to downright harmful. I’ve used a handful of these at various points in my posting career, and honestly I regret my small bit of negative influence on the communities where I practiced it. When I look at the practices on places like Hacker News nowadays, I can’t help but wonder how many people employ these or similar methods, and how much of the behavior is considered acceptable now because of the precedent set by me and others like me.

The worst part is, these strategies appear to work and work reliably. The first two, shitposts and junk submissions, are almost disgusting in how reliable they are after a bit of practice. They don’t educate anybody, they don’t elevate the conversation, but damned if they don’t increment that karma every time bit by bit

Hopefully, the techniques presented above will give everyone a clearer idea of the sorts of things they shouldn’t support and condone in their sites, and also help make it easier to detect when these things are being used in their presence. Ideally, if we are all so informed, we can stop ourselves from being exploited.

Also, as you may note, a lot of these behaviors with only slight modification can result in really helpful and engaging discussion. Posting articles that are relatable and educational instead of being clickbait, making jokes that rely on a technical knowledge and help illustrate points and teach—these are things that manage to help instead of hurt, but can so easily go the other way.

In the final part of this series, I’ll discuss the things that I think site maintainers can do to help encourage good behavior and to help limit the viability of these techniques.

HN/Lobsters: Good News, Bad News, How to Win Big (Part 1)

In this post, I’m going to talk about good and bad behaviors one can use to gain karma on sites like HN or Lobsters.

Most of the behaviors for these websites involve getting more karma. For those unfamiliar, karma/internet dollars/Paul Graham Funbucks is a system whereby a signed integer is incremented and decremented at the whims of the community. This integer is then used to rank comments, rank submitted stories, and generally provide access to the rarefied atmosphere of the Top Posters Club.

Why would we do this?

In the case of HN, I think it’s worth pointing out the flaws in the system so people don’t run the risk of losing actual money or getting screwed during their applications to YC (which requires your username on HN). Similarly, while I used to joke about Paul Graham funbucks (HN karma), the fact is that with the rise of “Apply HN” there are even more reasons to take a critical look at the rules and rewards of the site.

In the case of Lobsters, it’s been a damned fine community and it probably has at least another year or so before culture rot sets in. We’ve already had a couple of incursions, but we’ll see. For that community, I mean this to be a sort of “Hey, watch out, there can be problems with certain things we’ve flirted with normalizing”.

Okay, who’s this for?

My primary audience for this article are the moderators, sysops, and owners of these (and similar) communities. With any luck, the discussions of the mechanisms used in sites like Hacker News and Lobsters here will be useful for future community development.

My secondary audience for this article is fellow posters. I am going to try and explain how to best accrue karma on your aggregator of choice. You may already know one or all of these techniques, but I figure there’s a chance you’ll learn something or that you may find a way of improving on what I’ve documented here. More importantly, this series should help you develop a sense for how the system can be gamed and how to spot other posters doing so. Note that, if you decide to use the techniques in the next “Bad News” post, you are part of the problem. Please, follow the good parts here, and avoid the bad parts.

In this series I’ll be using a mental model of those two communities and their subject matter as well as occasionally illustrating examples with users or events. I neither condemn nor endorse any of the users or stories mentioned, bringing them up solely to provide context. Much of my discussion assumes that I have an accurate picture of what the communities care about; this may not be the case at all, but I have to start somewhere.

This post may not apply at all into other communities. Reddit, despite having a superficially similar karma mechanism, has very different moderation and other factors that prevent these writings from mapping over automatically.

The Good News

The good news is that most of the behaviors that are good for karma are good for the community:

  • Submitting interesting stories

  • Making insightful comments

  • Asking useful questions

  • Being polite to other posters

Interesting stories

Submitting interesting stories is the best low-volume way to get karma. After an initial burst of upvotes, a story tends to get a long-tail of karma over time. If your comments are only averaging, say, 2-3 points each, submitting stories is a better investment.

In a system like HN or Lobsters, stories that are off-topic or bad tend to get flagkilled by the hiveminds (communities of posters) or nuked/removed by the admins. So, they tend to have a limited amount of harm they can do to your karma (unless you egregiously screw up, but if you submit links to Stormfront or something you should expect that kind of reaction). This is much safer than comments, which can be continually downvoted and drain karma.

Insightful comments

Making insightful comments is the next best way to get karma. If you politely reason through a post and make an effort to stay on-topic or share relevant experiences then you will have a successful posting career. Somebody posting their own stories about a startup, being on a development team, or whatever else will almost always get karma because they’ve added to the conversation.

One has to be careful: the hivemind may well disagree with a clearly-reasoned comment regardless of politeness if it goes against the grain. HN has gotten particularly bad about this in the last couple of years, while Lobsters still seems to reward civility. Things likely to trigger the hivemind:

  • Rehashing a common sentiment frequently in post (as, say, michaelochurch does talking about their views on the startup ecosystem)

  • Being overly verbose or meandering (as, say, I do from time to time)

  • Being overly critical without padding with friendly reassurance

  • Defending American conservative positions (on HN, sometimes on Lobsters) without sources

  • Defending American socialist positions (HN and Lobsters, especially regarding Labor organization of devs)

  • Defending superficially abhorrent claims (anything involving, say, Moldbug) without sources

  • Attacking any sort of minority (deservedly or not) especially without really solid sources

  • Discussing the mokitas (purposefully-ignored truths) of the ecosystem

  • Posting in a way that gives the industry a bad name (almost everyone de facto agrees that exploiting users is okay, but don’t ever mention that on HN)

(Aside: I really should do a post on the mokitas of these communities.)

Useful questions

Asking useful questions is another great way to gain karma. If you ask for clarification in a discussion thread, it is very difficult to antagonize anybody else (unless you’re trying). Additionally, people will often upvote you in appreciation for the additional insights you were able to coax out. In general, questions tend to increase the value of the discussions for everyone and are just a really good idea.

I’ve found that asking for specific experiences or techniques does better than asking broad questions, unless you are willing to “prime” the responses a little bit by explaining the sort of answer you’re looking for. For an example:

How do you feel about your job?

The above can be vastly improved with a little context:

How do you feel about your job (at Bobco)? Like, what managerial stuff bothers you?

This sets the stage a bit better and helps a prospective answerer actually give the information you need. More specific information gives better discussion, and better discussion gives better karma.

Being polite

Being polite to other users is perhaps the least-profitable way of making karma. It does, however, prevent the loss of karma. Karma lost is basically karma you’ll have to earn back later, and when you are impolite people tend to downvote you far in excess of what you would’ve deserved had you merely been wrong.

Being polite doesn’t mean agreeing. Being polite doesn’t mean being respectful. Being polite doesn’t even mean being nice. Those are all things that are come after, but if you can’t be polite you won’t even get that far.

So, here are some of the ways I’ve found to be polite (without accidentally being any of those other things):

  • Always use the first-person plural (“we”) instead of the second-person anything. This makes it seem like you are on the same side as the other person, and reminds both of you that whatever the current disagreement, you probably just need to clarify your positions. The use of “you” tends to read as overly divisive and aggressive. This habit can be misinterpreted, but overall it makes things nicer.

  • Use “one would” instead of “you would” for speculating on a general case. This prevents some very messy misunderstandings.

  • Never, ever, ever make an obvious personal attack. They are rhetorically difficult to defend, and they just piss people off. Similarly, never call other people names.

  • Always be aware what you are stating as fact and as opinion. “X is rubbish” is similar to name-calling, but “I find X to be rubbish” is a matter of opinion, and at least on Lobsters people pick up on that and make allowances.

  • Never project behaviors or motivations onto other people. “You are a misogynist” leaves one open to factual critique (“Then why did I donate to Feminist Frequency?”)—prefer clarification like “This thing you said appears misogynistic…is that what you meant?”. Doing so elevates the discussion, and makes you seem more thoughtful than you would if you just label things.

  • Assume good-faith when replying to others. If somebody says something really upsetting, seek clarification (as above) in hopes than understand their position better. It may turn out that they just had a typo; even if they double-down, asking clarification is tantamount to asking a question, which is the third best way to get karma!

  • Avoid summarization, prefer direct quotes. Especially in divisive areas, people tend to use biased summaries of what their perceived opponent is saying. So, use direct quotes to avoid things devolving into you and your opponent arguing about positions neither of you hold.

There are other ways to be polite, of course, but the above are some of the most common and troublesome things I’ve run into in my posting career.

Looking Back on Malloc()

A friend of mine is currently doing a class assignment—one I too attempted years ago—and in the process of talking about it with him I’ve been going back down memory lane.

When I tried it my partner and I ended up failing miserably because of a few things, least of which being a complete lapse in judgement and deciding not to use source control. We also tried doing some cleverness with segmented best-fit lists, and it basically just ended in tears.

But, I’m older (hah) and wiser (hah hah) and so I’ve got a few more interesting things to say about it now. I might even go and throw up some code snippets on Github and relive my traumatic past. Anyways, onwards.

Basic of memory allocation in ‘nix

So, assume that we’ve got a process running with some heap. In this process, we decide that we want to allocate additional memory on the heap (maybe because we don’t have TCO or something—we don’t want to just extend the stack indefinitely).

Anyways, there’s an ending to the heap segment, and any attempts to access memory past this point are going to result in a segfault. To extend this segment, we use the brk or sbrk call (here is the wiki article on these). Note that on Windows you’ll be using the HeapAlloc() and related functions, and never have to actually deal with this sort of nonsense (see here). Note also that in modern ‘nix you’ll probably be using mmap() instead. For learning, though, let’s ignore those other more reasonable functions.

Last note—sbrk and family is not thread-safe, hence the use of other functions. So, unless we’re writing a custom allocator for Ruby or Node (lol), we won’t want to use it.

Malloc, version 0.0

The most brain-dead version of malloc() and free() would look like this (ignoring some of the additional functions posted here):

#define URFP(x) ((void)x)

void* malloc( size_t len ) {
    return sbrk( len );

void free( void* ptr) {
    URFP(ptr); /* do nothing */

The obvious problem with this, though, is that it will merrily leak memory and eventually fail. It’s also slow, because it has to hit a system call boundary.

This is also not great, because we want to actually track allocations, and this won’t let us do anything. So, where can we stash that information?

Malloc, version 0.5

So, let’s go and update our malloc to do a bit of extra tracking. This is a good way of showing a trick we’ll be making a lot of use of—writing hidden headers for our bookkeeping while still returning a pointer that is useful to the users. This same style of trick, incidentally, is used by Redis!

typedef struct {
    size_t allocation_size;
} alloc_record_t;

void* malloc( size_t len ) {
    /* allocate enough room for the requested allocation plus its record */
    alloc_record_t* rec = (alloc_record_t*) sbrk( len + sizeof(alloc_record_t));

    /* set the length */
    rec->allocation_size = len;

    /* return a pointer to the user-space view of the allocation */
    return ((char*)rec) + sizeof(alloc_record_t);

void free( void* ptr) {
    /* note that we offset the supplied user-space
       pointer to get the allocation record header */
    alloc_record_t* rec = (alloc_record_t*) (ptr - sizeof(alloc_record_t));

    /* do something to show the allocation */
    printf("Would've freed allocation at %p of size %z\n", ptr, rec->allocation_size);

Ideally you’d want to check for weird edge cases, like passing in a NULL ptr to free(), or a length to malloc() so large that it causes the arithmetic on sbrk() to overflow. In our case, though, we’ll be ignoring those practical issues so we can focus on the allocation theory.

Now, we still have a useless free(), and you might wonder why we don’t attempt to use sbrk() with a negative length in order to shrink the heap back down. We can do this, but we’d need to only free allocations at the end of the heap for that to work properly—if you freed an allocation in the middle somewhere naively, you’d end up shrinking the heap into actively used memory.

In order to do the correct thing we’d need to keep a list of deallocated blocks, only deallocate blocks located at the end of the heap, and continue shrinking only as long as the list of deallocated blocks contains a block adjacent to the end of the heap. Such a list, incidentally, we’ll call a free list from here on out.

Anyways, it’d be a pain in the ass, and wouldn’t help us.

Wrapping up

Next time, I’ll talk about implementing a free list and basically creating a memoized version of sbrk(). I’ll also talk about some other ways of improving our allocation library to be faster and more interesting.

Further reading

Dynamic Storage Allocation: A Survey and Critical Review has a really thorough review of different allocation methods and bookkeeping techniques.