Projects

Recent blog entries by kr

Do This

Use the Gmail web UI with shortcut keys.

Mute. Heavily. The m shortcut key is your friend.

Triage. Your one and only goal for processing your inbox is to make it empty. Not to actually do anything productive, because processing email is inherently anti-productive. Don’t fool yourself into thinking you’re doing work here. Just get it over with as quickly as possible. For each message in your inbox, quickly choose one of these things:

Mute the conversation. (Press m.)

Read (or skim) it and archive. (Press e.)

If it requires action and it’ll take you less than 30 seconds, DIFN and archive the message. (Press e.)

If it requires action and it would take you 30 seconds or more, star and archive it immediately. (Press s then e.)

It is permitted to begin replying to a message and then realize it’ll take longer than you thought. In that case you should defer the rest of your reply. (Press se.)

If it takes you more than, say, three seconds to decide which thing to do, star and archive. (Press se.)

You can get rid of a hundred threads this way in five minutes. Now your inbox is empty. You’re welcome. You still have a to-do list, and it is not empty.

Check starred items. Press g then s. Open this folder regularly. gs. It’s your new home. Learn to love it. gs. If there were a way to make this folder the one you see first when you log in, I would tell you to do that.

Process your inbox again! gi. Later, at some time in the future, when you feel emotionally centered. Maybe after you’ve completed something from your starred items and you’re feeling good about yourself. gi. Certainly not while you’re in the middle of doing something useful. But don’t just “check” your inbox, process it. If you’ve gone to the trouble of opening it up, you might as well rip through those messages (there are only like two of them now since it was empty before) and get it empty again.

Survey the universe. gsgi. It’s easy to bounce between these two folders. gsgi. You know, get an overview of what’s going on. Expect to have 0–4 items in each of these folders most of the time. Tending toward the 0 side. Not too bad, eh?

Pick one thing from your starred items and do that thing.

When you’ve finished, unstar it. (Press u to go back to the starred items list and s to unstar it. The gesture to remember is us.)

That’s it, really. Looks like a lot of rules, now that I’ve typed them all out, but it’s not so bad. Just remember, triage.

Do Not

Do not mark as unread. To-do items are hereby banned from your inbox. Also, you don’t need that this-item-is-unread-and-the-font-is-bold visual treatment to distinguish to-do items from other mail. A star is sufficient. Your to-do list, the starred items folder, is such a tranquil place now. Namaste. (Exception: you’re looking at a message and legitimately don’t have time to read it because you must abort processing mail. Mark it as unread and leave it in the inbox with all the other messages you actually haven’t read.)

Do not use priority inbox. Turn it off; you don’t need it any more. Classic inbox all the way. Those little yellow “important” markers? Turn those off too. They’re nothing but a distraction.

Do not use push notifications for incoming mail on your phone. You really don’t want to be interrupted, distracted by incoming mail while you’re doing actual work. You decide when to process your inbox.

Frequently Anticipated Questions

Keith, why are you blogging about methods for email productivity?

I’m not a fan of heavy process. GTD makes me squirm. I’m more of a DIFN kind of guy. But email is a problem. I get a lot of it. Some of you probably get more. Ignoring the problem didn’t work. Simply D-ing IFN isn’t good enough when I have more than one thing to do. And the instinctive, thoughtless mark-as-read-and-leave-in-the-inbox-as-my-todo-list had become a quagmire. I had an ever-growing inbox and an ever-sinking feeling in the pit of my stomach. And one day I snapped, and decided to do something about it. One word appeared in my head, unbidden, fully-formed, as if from the head of Zeus: triage. Everything here is an outgrowth of that seed.

Isn’t it bad to use email as a to-do list?

We all do it. Stop feeling guilty about that. Embrace it.

Doesn’t this just move your to-do list to another place? How does it actually help?

Out of sight, out of mind. Just seeing all the crap you have to do increases cognitive burden. Seeing more crap you may or may not have to do but which is simply mixed in with the crap you actually have to do pushes cognitive burden over the edge. That’s the key: your inbox mixes to-do items with legitimately unread mail, while starred items gives you a much quieter, tractable to-do list.

Another useful, subtle property about keeping to-do items out of your inbox: it’s totally obvious when you’re done triaging. You simply run out of mail. There’s no “oh I think I got to all the new mail here, everything that’s left is stuff I’ve seen before”. No need to discern.

How can I avoid falling into the trap of spending too much time on certain inbox messages?

Remember, triage. Getting to inbox zero means outpacing the inflow of mail, and that means quick decision-making. You’re a battlefield medic deciding which limbs to save and which to amputate; time is not on your side.

What if I already use stars for something else?

Then maybe this system isn’t for you. Low friction is crucial to making this work. Anything that takes more than one or two keystrokes to use is too hard to use consistently. Yes, you could use a “todo” label, even from the keyboard. But typing gltodo⏎ (or even glt⏎) to view it is too slow. Latency kills. Star is s, one keystroke.

Luckily for me, I never used to use stars for anything. I had one or two messages starred randomly for no good reason. Those are gone now. We’re going to make good, heavy use of stars here. Let no starry emotional baggage get in the way; we’re completely commandeering your stars.

Why can’t I just mark-as-unread in my inbox?

Actual to-do items get lost in the noise. Mark-as-unread makes it take more effort than necessary to reason whether a given email is something you’ve looked at and decided to put off or something you actually haven’t seen before. This makes the task of processing email itself a nice candidate for putting off, since it takes so long.

Take back the “unread” state. Mark as unread only those messages you really haven’t read. Now it means what it says.

Should I use a multi-inbox feature to see starred items and inbox items side-by-side in one view?

No. It’s a good thing that the starred items are on a separate screen from the inbox. The combined view of both at once is an anti-pattern. You’re either processing inbox mail or doing work, not both. Focus.

How does my smartphone fit into this?

I don’t know about you, but I hate typing on my phone. Hate. It. Short text messages are ok, but typing an email doesn’t work. “I feel that my thoughts are being forced out through a straw.” So I never do real work on my phone or even send replies. But triage, on the other hand… triage is easy and fast. Recent incarnations of the Gmail iOS app are quite decent, and, crucially, contain a mute button (sadly lacking in the otherwise-excellent Sparrow). Phone triage is an effective way to stay on top of your inbox, especially when your coworkers are as maddeningly productive as mine.

“Stay on top of” my inbox? Really? That sounds awful.

Believe me, it’s easy, but let me clarify: do not worry about staying on top of your inbox. Just process mail whenever you want, every 5 minutes, every 5 hours, whatever. Don’t worry about unread email piling up. 5, 10, 20, more unread messages? No sweat. Processing them is easy. You can (and should) do it on your terms.

How do I compose a new message without being distracted by my inbox and feeling compelled to process it?

I’ve been keeping my default view on Gmail the drafts (or some other easily accessible but usually empty folder) so I can switch to Gmail to do basic composing/searching without being hit in the face with new messages. Works pretty well once you get in the habit of switching to the empty folder as an ”I’m done for now” kind of gesture at the end of your processing sessions.

The shortcut sequence to switch to the drafts folder is gd.

Also remember: it’s okay to leave unread email in your inbox. You always decide when to process it.

But System X already does this! Nothing new here.

That’s not a question, but I’ll answer it anyway. First, the other systems I’ve seen certainly share some characteristics and use some of the same psychological tricks, but they’ve all felt really complicated to me. I don’t want to have to learn a hundred rules about how to organize my note cards into projects and tasks with colors and categories and… yuck. So this system is as simple as I could make it. Most of the rules are about getting rid of stuff. (Though, looking over that list above, I still wish I could make it shorter.) And it doesn’t require any special tools, just the Gmail web UI. Second, I’m sure there are lots of productivity systems out there I’ve never heard of, so maybe there’re already some systems out there just as good as this one. Good for them.

Conclusion

So, does all this work? I didn’t know when I started out, but figured it was worth a shot at least. My biggest worry was that I’d just move the problem to another place: instead of an ever-growing inbox I’d have an ever-growing starred items folder. But a curious thing happened. My heavy inbox burden shrank a bit after the first processing session. And it just kept shrinking. My new starred items burden feels qualitatively different. Staring at a bold to-do-list inbox makes it all too easy to throw up your hands and close the browser. After all, even if you were to pick one of those emails and take care of it, it’d probably be replaced with 3 more, like a hydra, by the time you returned to your inbox. The ground is constantly shifting under you. On the other hand, your starred items folder only ever contains things that you put there. You can look at it, pick one thing to do, do that thing, and look again: there is now one fewer thing! You and you alone decide when to process incoming mail and star new messages. This might seem like an academic distinction, but let me tell you, it feels worlds apart, and I actually manage to knock off my starred items at a regular pace. They don’t pile up.

Now, getting to inbox zero is no longer some Herculean achievement, no longer worthy of announcing to the world. After a few weeks doing this stuff I didn’t just get there, I’ve stayed at inbox zero virtually the entire time. And it feels pretty easy to maintain that way. I expect no inbox creep in my future. Inbox zero for life!

There is no shortage of tools that provide one of these properties or the other. For example, mysql, postgres, and redis provide consistency but not high availability; riak, couchdb, and redis cluster (when it’s ready) provide high availability but not consistency. The only freely-available tool that attempts to provide both of these is zookeeper, but zookeeper is specialized, focused on locking and server management. We need a general-purpose tool that provides the same guarantees in a clean, well-designed package.

Background

Soon after I started working at Heroku, Blake Mizerany got me involved in designing a “distributed init” system, something that could manage processes across multiple machine instances and recover gracefully from single instance failures and network partitions. One necessary building block for this is a network service that can provide synchronization for its clients – in other words, locking.

When we started building this distributed process monitor, we quickly realized that the lock service should be packaged as a separate tool. In true Unix style, it strives to do one thing well. In fact, doozer doesn’t actually provide locks directly. Its “one thing” is consistent, highly-available storage; locks are a separate thing, that clients can implement on top of doozer’s primitives. This makes doozer both simpler and more powerful, as we’ll see in a moment.

Locks Are Not Primitive Enough

Other similar systems (for example Chubby, Zookeeper2) provide locks as a primitive operation, alongside data storage. But that requires the lock service to decide when the holder of a lock has died, in order to release the lock. In practice this means that every client that wants to obtain a lock must establish a session and send periodic heartbeat messages to the server. This works well enough for some clients, but it’s not always the most appropriate way to determine liveness. It’s particularly troublesome when dealing with off-the-shelf software that wasn’t designed to send heartbeat messages.

Doozer takes a different approach. It provides only data storage and a single, fundamental synchronization primitive, compare-and-set. This operation is complete (you can build any other synchronization operation using it), but it’s simpler than a higher-level lock, and it doesn’t require the server to have any notion of liveness of its clients.

In the future, doozer might ship with companion tools that provide higher-level synchronization for users that want it, but these tools will operate as regular doozer clients, and they’ll be completely optional. If you don’t need their services, just don’t run them; if you need something slightly different from what they provide, you are free to make your own.

What is it good for?

How does doozer compare to other data stores out there? Redis is amazingly fast, with lots of interesting data structures to play with. HBase is amazingly scalable. Doozer isn’t particularly fast or scalable; its claim to fame is high availability.

Doozer is where you put the family jewels.

The doozer readme has a few concrete examples, but consider this one: imagine you have three redis servers – one master and two slaves. If the master goes down, wouldn’t it be nice to promote one of the slaves to be the new master? Imagine trying to automate that promotion. You’ll have to get all the clients to agree which one to use. It doesn’t sound easy, and it’s even harder than it sounds. If there is a network partition, some of the clients might disagree about which slave to promote, and you’d wind up with the classic “split-brain” problem. If you want this promotion to work reliably, you have to use a tool like doozer, which guarantees consistency, to coordinate the fail-over.

Using Doozer

We have client drivers for Go (doozer) and Ruby (fraggle), with an Erlang driver in the works. The doozer protocol documentation gives the nitty-gritty of talking to doozer, but most of you will be interested in the interface provided by the driver you’re using; they each have documentation.

The words “consistency” and “high availability” have several reasonable definitions, and people too often use them without saying exactly what they mean. When I speak of consistency, I mean absolute prevention of inconsistent writes. The phrase “eventual consistency” is a synonym for “inconsistency”. When I speak of high availability, I mean primarily the ability to face a network partition and continue providing write service to all clients transitively connected to a majority of servers. Secondarily, I mean the ability to continue providing read-only service to all clients connected to any server. Update: This is not the same as being “available” in the sense of the frequenetly-cited and almost-as-frequently-misunderstood CAP theorem. Coda Hale has a good discussion of the CAP theorem’s applicability to real-world systems. In those terms, we choose consistency over availability.

There is no shortage of tools that provide one of these properties or the other. For example, mysql, postgres, and redis provide consistency but not high availability; riak, couchdb, and redis cluster (when it’s ready) provide high availability but not consistency. The only freely-available tool that attempts to provide both of these is zookeeper, but zookeeper is specialized, focused on locking and server management. We need a general-purpose tool that provides the same guarantees in a clean, well-designed package.

Background

Soon after I started working at Heroku, Blake Mizerany got me involved in designing a “distributed init” system, something that could manage processes across multiple machine instances and recover gracefully from single instance failures and network partitions. One necessary building block for this is a network service that can provide synchronization for its clients – in other words, locking.

When we started building this distributed process monitor, we quickly realized that the lock service should be packaged as a separate tool. In true Unix style, it strives to do one thing well. In fact, doozer doesn’t actually provide locks directly. Its “one thing” is consistent, highly-available storage; locks are a separate thing, that clients can implement on top of doozer’s primitives. This makes doozer both simpler and more powerful, as we’ll see in a moment.

Locks Are Not Primitive Enough

Other similar systems (Chubby, Zookeeper) provide locks as a primitive operation, alongside data storage. But that requires the lock service to decide when the holder of a lock has died, in order to release the lock. In practice this means that every client that wants to obtain a lock must establish a session and send periodic heartbeat messages to the server. This works well enough for some clients, but it’s not always the most appropriate way to determine liveness. It’s particularly troublesome when dealing with off-the-shelf software that wasn’t designed to send heartbeat messages.

Doozer takes a different approach. It provides only data storage and a single, fundamental synchronization primitive, compare-and-set. This operation is complete (you can build any other synchronization operation using it), but it’s simpler than a higher-level lock, and it doesn’t require the server to have any notion of liveness of its clients.

In the future, doozer might ship with companion tools that provide higher-level synchronization for users that want it, but these tools will operate as regular doozer clients, and they’ll be completely optional. If you don’t need their services, just don’t run them; if you need something slightly different from what they provide, you are free to make your own.

What is it good for?

How does doozer compare to other data stores out there? Redis is amazingly fast, with lots of interesting data structures to play with. HBase is amazingly scalable. Doozer isn’t particularly fast or scalable; its claim to fame is high availability.

Doozer is where you put the family jewels.

The doozer readme has a few concrete examples, but consider this one: imagine you have three redis servers – one master and two slaves. If the master goes down, wouldn’t it be nice to promote one of the slaves to be the new master? Imagine trying to automate that promotion. You’ll have to get all the clients to agree which one to use. It doesn’t sound easy, and it’s even harder than it sounds. If there is a network partition, some of the clients might disagree about which slave to promote, and you’d wind up with the classic “split-brain” problem. If you want this promotion to work reliably, you have to use a tool like doozer, which guarantees consistency, to coordinate the fail-over.

Using Doozer

We have client drivers for Go (doozer/client) and Ruby (fraggle), with an Erlang driver in the works. The doozer protocol documentation gives the nitty-gritty of talking to doozer, but most of you will be interested in the interface provided by the driver you’re using; they each have documentation.

The words “consistency” and “high availability” have several reasonable definitions, and people too often use them without saying exactly what they mean. When I speak of consistency, I mean absolute prevention of inconsistent writes. The phrase “eventual consistency” is a synonym for “inconsistency”. When I speak of high availability, I mean primarily the ability to face a network partition and continue providing write service to all clients transitively connected to a majority of servers. Secondarily, I mean the ability to continue providing read-only service to all clients connected to any server. Update: This is not the same as being “available” in the sense of the frequenetly-cited and almost-as-frequently-misunderstood CAP theorem. Coda Hale has a good discussion of the CAP theorem’s applicability to real-world systems. In those terms, we choose consistency over availability.

There is no shortage of tools that provide one of these properties or the other. For example, mysql, postgres, and redis provide consistency but not high availability; riak, couchdb, and redis cluster (when it’s ready) provide high availability but not consistency. The only freely-available tool that attempts to provide both of these is zookeeper, but zookeeper is specialized, focused on locking and server management. We need a general-purpose tool that provides the same guarantees in a clean, well-designed package.

Background

Soon after I started working at Heroku, Blake Mizerany got me involved in designing a “distributed init” system, something that could manage processes across multiple machine instances and recover gracefully from single instance failures and network partitions. One necessary building block for this is a network service that can provide synchronization for its clients – in other words, locking.

When we started building this distributed process monitor, we quickly realized that the lock service should be packaged as a separate tool. In true Unix style, it strives to do one thing well. In fact, doozer doesn’t actually provide locks directly. Its “one thing” is consistent, highly-available storage; locks are a separate thing, that clients can implement on top of doozer’s primitives. This makes doozer both simpler and more powerful, as we’ll see in a moment.

Locks Are Not Primitive Enough

Other similar systems (Chubby, Zookeeper) provide locks as a primitive operation, alongside data storage. But that requires the lock service to decide when the holder of a lock has died, in order to release the lock. In practice this means that every client that wants to obtain a lock must establish a session and send periodic heartbeat messages to the server. This works well enough for some clients, but it’s not always the most appropriate way to determine liveness. It’s particularly troublesome when dealing with off-the-shelf software that wasn’t designed to send heartbeat messages.

Doozer takes a different approach. It provides only data storage and a single, fundamental synchrionization primitive, compare-and-set. This operation is complete (you can build any other synchronization operation using it), but it’s simpler than a higher-level lock, and it doesn’t require the server to have any notion of liveness of its clients.

In the future, doozer might ship with companion tools that provide higher-level synchronization for users that want it, but these tools will operate as regular doozer clients, and they’ll be completely optional. If you don’t need their services, just don’t run them; if you need something slightly different from what they provide, you are free to make your own.

What is it good for?

How does doozer compare to other data stores out there? Redis is amazingly fast, with lots of interesting data structures to play with. HBase is amazingly scalable. Doozer isn’t particularly fast or scalable; its claim to fame is high availability.

Doozer is where you put the family jewels.

The doozer readme has a few concrete examples, but consider this one: imagine you have three redis servers – one master and two slaves. If the master goes down, wouldn’t it be nice to promote one of the slaves to be the new master? Imagine trying to automate that promotion. You’ll have to get all the clients to agree which one to use. It doesn’t sound easy, and it’s even harder than it sounds. If there is a network partition, some of the clients might disagree about which slave to promote, and you’d wind up with the classic “split-brain” problem. If you want this promotion to work reliably, you have to use a tool like doozer, which guarantees consistency, to coordinate the fail-over.

Using Doozer

We have client drivers for Go (doozer/client) and Ruby (fraggle), with an Erlang driver in the works. The doozer protocol documentation gives the nitty-gritty of talking to doozer, but most of you will be interested in the interface provided by the driver you’re using; they each have documentation.

The words “consistency” and “high availability” have several reasonable definitions, and people too often use them without saying exactly what they mean. When I speak of consistency, I mean absolute prevention of inconsistent writes. The phrase “eventual consistency” is a synonym for “inconsistency”. When I speak of high availability, I mean primarily the ability to face a network partition and continue providing write service to all clients transitively connected to a majority of servers. Secondarily, I mean the ability to continue providing read-only service to all clients connected to any server. Update: This is not the same as being “available” in the sense of the frequenetly-cited and almost-as-frequently-misunderstood CAP theorem. Coda Hale has a good discussion of the CAP theorem’s applicability to real-world systems. In those terms, we choose consistency over availability.

There is no shortage of tools that provide one of these properties or the other. For example, mysql, postgres, and redis provide consistency but not high availability; riak, couchdb, and redis cluster (when it’s ready) provide high availability but not consistency. The only freely-available tool that attempts to provide both of these is zookeeper, but zookeeper is specialized, focused on locking and server management. We need a general-purpose tool that provides the same guarantees in a clean, well-designed package.

Background

Soon after I started working at Heroku, Blake Mizerany got me involved in designing a “distributed init” system, something that could manage processes across multiple machine instances and recover gracefully from single instance failures and network partitions. One necessary building block for this is a network service that can provide synchronization for its clients – in other words, locking.

When we started building this distributed process monitor, we quickly realized that the lock service should be packaged as a separate tool. In true Unix style, it strives to do one thing well. In fact, doozer doesn’t actually provide locks directly. Its “one thing” is consistent, highly-available storage; locks are a separate thing, that clients can implement on top of doozer’s primitives. This makes doozer both simpler and more powerful, as we’ll see in a moment.

Locks Are Not Primitive Enough

Other similar systems (Chubby, Zookeeper) provide locks as a primitive operation, alongside data storage. But that requires the lock service to decide when the holder of a lock has died, in order to release the lock. In practice this means that every client that wants to obtain a lock must establish a session and send periodic heartbeat messages to the server. This works well enough for some clients, but it’s not always the most appropriate way to determine liveness. It’s particularly troublesome when dealing with off-the-shelf software that wasn’t designed to send heartbeat messages.

Doozer takes a different approach. It provides only data storage and a single, fundamental synchrionization primitive, compare-and-set. This operation is complete (you can build any other synchronization operation using it), but it’s simpler than a higher-level lock, and it doesn’t require the server to have any notion of liveness of its clients.

In the future, doozer might ship with companion tools that provide higher-level synchronization for users that want it, but these tools will operate as regular doozer clients, and they’ll be completely optional. If you don’t need their services, just don’t run them; if you need something slightly different from what they provide, you are free to make your own.

What is it good for?

How does doozer compare to other data stores out there? Redis is amazingly fast, with lots of interesting data structures to play with. HBase is amazingly scalable. Doozer isn’t particularly fast or scalable; its claim to fame is high availability.

Doozer is where you put the family jewels.

The doozer readme has a few concrete examples, but consider this one: imagine you have three redis servers – one master and two slaves. If the master goes down, wouldn’t it be nice to promote one of the slaves to be the new master? Imagine trying to automate that promotion. You’ll have to get all the clients to agree which one to use. It doesn’t sound easy, and it’s even harder than it sounds. If there is a network partition, some of the clients might disagree about which slave to promote, and you’d wind up with the classic “split-brain” problem. If you want this promotion to work reliably, you have to use a tool like doozer, which guarantees consistency, to coordinate the fail-over.

Using Doozer

We have client drivers for Go (doozer/client) and Ruby (fraggle), with an Erlang driver in the works. The doozer protocol documentation gives the nitty-gritty of talking to doozer, but most of you will be interested in the interface provided by the driver you’re using; they each have documentation.

The words “consistency” and “high availability” have several reasonable definitions, and people too often use them without saying exactly what they mean. When I speak of consistency, I mean absolute prevention of inconsistent writes. The phrase “eventual consistency” is a synonym for “inconsistency”. When I speak of high availability, I mean primarily the ability to face a network partition and continue providing write service to all clients transitively connected to a majority of servers. Secondarily, I mean the ability to continue providing read-only service to all clients connected to any server.