What I love about working at Twitter

I’ve never been the one with the fancy words and clever insights. My writing is either hastily-scribbled thoughts to myself, or simple language and simple meaning to convey a message. If you’re looking for the poetic literature on this subject, I recommend my colleague Jeremy’s Medium post, “Why I Love Twitter“.

Twitter is the first company I’ve worked for whose product I use every day. I’ve never had that before, and I never realised how significant that is, before this job. It’s incredibly satisfying to work on a website you depend on yourself. It becomes a labour of love.

The Twitter site always appears to be very simple. There’s reliably someone on HackerNews each week claiming they could build it in a day, and before I came here, that could well have been me. Since joining, I’ve learned of the tremendous complexity that underlies essential services, like Twitter, Facebook and Google, to keep them running 24/7. Why is 24/7 just hours and days? It’s not enough. Every second of every year, you expect Twitter to be there when you ask for it.

And at scale! We serve hundreds of millions of users! Our Google Analytics numbers are just ridiculous to browse through. (I’ve wasted hours in those dashboards – hours). I love working at scale. After 16 years building websites, I’ve learned that the most fun work is realtime, scale, and user-focused. The kids say they love Machine Learning and Big Data these days, but they’re honestly missing out. I love the breakneck pace of developing for users, the tension of stability, and the challenges of scale.

When I read the news (BBC), nearly every story mentions Twitter or a Tweet. Everything. Politicians making announcements, or campaigning, or discussing foreign affairs. Celebrities doing whatever it is they do. Every single obituary. It’s the perfect way to get a short soundbite for a story. It’s the source of news on the ground. It’s a direct line to the people who matter. I love that we have this impact.

Nearly everyone, whether they use it or not, has an opinion on Twitter. You should do this, you should do that. Sometimes we agree, and there’s a technical constraint. Sometimes we agree, and we just haven’t got time for that yet. Sometimes we agree and it gets done! I love being on the inside and being able to sway those priorities.

This is, after all, a product I use every day.

For me, one of the perks of the job is little tweaks. I’m not a coder any more, I’m just a manager. But that doesn’t stop me making the *slightest* tweak here, the *slightest* tweak there. Just when I’ve got a free afternoon. Maybe I’ll speed up the page load. Maybe I’ll add another column. It all gets approved by others. There’s nothing underhand. And it’s all small, but I love that power.

When I joined Twitter, I felt incredibly unworthy. I assumed the coders there would be gods, writing these books and building these sites. What I found were humans. Ok, one or two are the exceptional kind, who could rebuild your templating engine in C over the weekend just for kicks, saving the company millions of dollars. But there are also many wonderfully talented normal humans doing great work. And I was proud to join them.

It’s been more than five years since I joined, but the company, the work, the job, the product, the environment, the world. It all keeps changing. A few years ago everyone said we were doomed. Then they said we were amazing. And now they say we’re doomed again. The faces at the top sometimes change. Sometimes often. But the team I work with, the team I build and run. This team is a constant. They’re always doing the best they can to serve our users. To keep the site running, the service alive. To make it better every day.

That is what I love about working at Twitter.

2015: This year I have …

Every year I scribble down a list of things I’ve done in the past 12 months.See previous years: 2014, 2013, 2012, 2011, 2010, 2009 and 2008.

This year, I ran a marathon (kind of – there was a lot of walking involved), we holidayed in Hawaii (twice) at the Disney Aulani, we flew home for the first London family Christmas since 2009, and we met my new niece.

At work, I’ve been really busy, with between 15 and 30 reports. We made some really strong hires, shipped some great new code and features, and finally killed the monorail. We had some tough times too, from which I’ve learned a lot.

As an effort to be a better manager, I’ve kicked off an MBA which I seriously don’t have time for. It’s interested to learn, but painful to find time for the coursework. I’m a terrible student. Especially at essays.

I had three wisdom teeth removed this year, which wasn’t fun at all. And in combination with a slight overdose of painkillers and a perforated sinus, I had a bad time. On the plus side though, I got really thin for a couple of months. I’m still syringing food out of my empty socket, which is exactly as gross as it sounds.

I really enjoyed being Daddy to a three year old full of energy. It’s been The Most Fun. I heartily recommend it.

I finally went to JSConf this year. It was an outstanding conference. Huge thanks to Chris and family. Sadly, it seems this year was the last – but hopefully they revive it someday.

Last year I said I’d get a cat. I failed. Partly because Amazon doesn’t deliver pets, and I don’t know any other way to buy things. Maybe next year. My wife wants a dog, which I’m really not sure about. Dogs are nasty. We’ll see.

This year I’ve been drinking more craft beers and really enjoying it. I’ve spent an enjoyable few nights sampling flavours in Øl, our local specialist beer shop. And I’ve invested the boy’s college fund in a local brewery. Should be fun to explain that to him in a few years.

Next year, I’m really excited about getting a VR kit at home. I daresay I won’t use it a lot (like my dusty Apple Watch), but it’ll be fun to play with.

Maybe we’ll buy a house. Get that (shudder) dog.

And I’d like to be fitter. More than anything, I’d like to be thin, fit and healthy by the end of 2016. Time to dig out that gym card.

How to walk a marathon

I ran the San Francisco marathon two weeks ago today. Previously (back in 2008), I ran London. San Francisco is hillier than London, and it doesn’t take much of a hill to tire you out. After getting close to the coast at 15 miles or so, I took a few walking breaks.

And, to be perfectly honest, I had a lot of company. Not even from just the full marathoners, but from the halfers too – and they’d only been at it for a couple of miles!

When you get to the top of the hills at around the 20 mile mark, you’d think it’s easy. The truth is that your legs muscles are just blown. You’ve been running for 3 or 4 hours at that point, and you can’t even walk down the hills. You just limp along with a grimace.

At 20 miles, I quit. I sat down by the side of the road. I said I’d had enough.

But then I thought, what now? I could call a taxi and get to the end, but really it’s only five miles. I could just walk the rest. so I did. And apart from some muscle pains for the rest of the day (and week), and some foot pain ever since – it was fine. I wrapped up in just under 6 hours.

If you look around online you’ll get lots of really great help on how to run a marathon. This will be from those California fitness freaks. They’ll be all eating healthy and training and yoga and sensible and stuff. But there’s not much out there for the slackers. Where is the guide for the fat, the lazy, the unwilling, or merely too busy? Here are my tips:

  • It’s a good idea to do some actual training. I can run 2 miles to the Bart station. That’s my training. Twice a week for four months. I’d call it the minimum.
  • Don’t eat before you run. You’ll get cramps. Eat after.
  • You should do one long run as practice. I did Bay to Breakers, which is an easy 7 miles. Don’t walk this one.
  • If you’re getting blisters after half an hour running, you need new shoes. That’s why you need the long training run. Get new shoes and wear them in. If you can also wear them at work, then you don’t need to carry so much on your commute.
  • If you’re tired or hurting, don’t stress – just skip a training session. You don’t need an injury. You don’t need to run until you hate it. Just enjoy it.
  • Don’t turn up early for the race. Why get tired standing around? Be there 10 minutes before your start time – no more.
  • Run light – there’ll be plenty of water stops with electrolyte. Maybe even food. Carry as little as possible.
  • Don’t go mad with the water. Don’t go mad for the gels and electrolytes. Take a little here and there. Take your favourite candy for the 18 mile mark.
  • Run with a friend who matches your pace. Seriously more fun. You can people-watch together, admire the views of SF and complain about how bad the gels taste.
  • If you don’t have a friend, get your playlist ready. Have some variety – after 3 hours you’ll be stressed out by everything and need some chill.
  • Know your route – you’ll be able to look forward to the flat bits and know where you can pee.
  • Run London if you can – there are crowds all the way. It’s flat.
  • Walk if you must, but try to avoid it. Get into a rhythm, or follow someone at your pace. There will seriously be lots of walkers. You’re not alone.
  • Wear a visor or a cap. While the pros will finish before breakfast, you’ll be out running at noon. Sunburn is a problem, and so is the sunlight.
  • Don’t try and hop up and down curbs while you run – your legs will suddenly stop working sooner than you think and you’ll fall.
  • You’ll be running for 5 or 6 hours. That’s not a marathon, that’s an ultramarathon. You’re awesome and let nobody tell you any different. All you need to do now is finish.
  • Final note: don’t die. Take a phone for emergencies.


I plan to publish a book for children.

It shall have a dust jacket, so that the books look crinkled and worn after a single use.

It shall have numerous title pages. It’s not enough to say the title on the cover alone. I would rather the title were repeated on the first page and second page too.

It shall have razor sharp corners, suitable for carving your name into diamonds, or for gouging eyes.

It shall have pages which are cut straight, such that grownups and children alike cannot turn a single page at a time.

It shall have popup controls that will be broken before it leaves the factory.

It shall have text that varies in both rhythm and rhyme. The plot will be absent of reason.

It shall be a classic.

2014: This year I have …

My annual End of Year update. See previous years: 2013, 2012, 2011, 2010, 2009 and 2008.

Last year, I made a long list of things I wouldn’t do this year. I only broke my promise on one thing: I bought a new car. Well, not a car – a truck. A big, beautiful, red, four-wheel drive, leather trimmed, all-american truck.

I was happy with that.

My son is now going to school, and talking like anything. It’s amazing to hear him put sentences together, have conversations, defend his turf, argue his position. Age three is great fun. And I think it will only get better next year.

He wears his Buzz Lightyear suit every single day.

My dad came to visit for the first time! We took him to Yosemite.

We drove up to Tahoe, and were surprised by 6 inches of snow overnight.

I finish the year at work with more than twenty reports. I’m now fully a manager instead of a coder – I’ve got five really strong teams of people I trust, and that’s excellent. I’m really enjoying learning to be a better manager.

Not that I don’t indulge in a little coding too. This year I made Twitter span three columns.

Next year, I plan to take a good holiday or two. I’d like to get more exercise. Maybe start running again. Maybe something different. And we’ll try and persuade more people to visit us.

Maybe we’ll get a cat.

Flight Mixins

We started building Flight.js at Twitter back in 2011. The brainchild of Dan Webb, it’s a component-based framework based on his previous frameworks polished with what we’d learned from working with Twitter’s existing codebase. One feature of the framework we wanted to include from the outset was Angus Croll‘s mixin model. His blog post on the subject is beautifully readable, and he’s also given a presentation on Flight’s mixin model at BrazilJS. It’s well worth reading both the blog and slide deck now, if you haven’t already.

Two and a half years later, with the whole of twitter.com now running on Flight, how do we feel about Flight and mixins? Are they working for us?

Rather than using the classical talking animals to describe our components, I’ll try to use real-life twitter components, though I’ll be dramatically simplifying for readability.

module.exports = defineComponent(customTimeline,
function customTimeline() {
    itemType: 'tweet'

Here’s an example of the code running our new Custom Timelines. As you can see, all the functionality is provided by our mixins. The code for our timeline is powerful, using delegated event handlers to pick up and handle most of the events sourced by the tweets themselves.


We’ve always described mixins as “specialisations”. The idea is that you’d write a module, and then extend it with extra functionality.

For example,

module.exports = defineComponent(newTimeline);

We could then add functionality like infinite scroll:

module.exports = defineComponent(newTimeline,

But if we break apart this model a little further, then things get complicated. The mixin is able to wrap and override code in our newTimeline model.

function newTimeline() {
  this.updateTimeline = function() {
    // something
function withInfiniteScroll() {
  this.around('updateTimeline', function(originalFunc) {
    // something

However, this doesn’t really make sense. If we follow this model, then we need to define the core methods of timeline in every single component that wants to use withInfiniteScroll. We also have no way to extend or override the behaviour of the mixin without using another mixin on top.

A far better model would be this:

module.exports = defineComponent(withInfiniteScroll,

Putting the mixins at the start of the component definition will allow us to override any behaviour we want. This is much more like mixins used by other languages (Ruby or Scala used here at Twitter, for example).

If we apply this new model back to our original component code, we get this:

module.exports = defineComponent(withBaseTimeline,

This is a simple change, but gives far more power to the customTimeline. Flight gives us this flexibility because it treats all the arguments to defineComponent as mixins. If you’re using Flight.js in the wild, I would strongly recommend making this change.


One thing that’s very clear from our Custom Timeline example is that our mixins have become reasonably verbose. If we wanted to create another similar Timeline component, we’d have to duplicate that whole definition.

module.exports = defineComponent(withBaseTimeline,
function newTimeline() {
    itemType: 'tweet'

Something we’ve done in a few cases is create mixin collections:

var compose = require('flight/lib/compose');
module.exports = customTimelineMixins;
function customTimelineMixins() {
  compose.mixin(this, [

This will work, but I dislike having to reach into the framework and apply the mixins myself. This is also taking us back to the idea of inheritance:

module.exports = defineComponent(customTimelineMixins,
module.exports = defineComponent(customTimelineMixins,

Ultimately, I think there is some value in this combination of mixins and inheritance. In wider discussions with the team at Twitter, we took this further. Ideally, we’d like to be able to treat a defined component just as another mixin.

module.exports = defineComponent(customTimelineComponent,

This isn’t possible in the framework today, but conceptually there’s no reason why we couldn’t treat every component as a collection of mixins, and defer the creation of the component itself until it is actually used for instantiation and attachment. I’m hoping something like this will make Flight v2.


One of the huge benefits of Flight is the enforcement of modularity. Each component is written and tested as a unit, and the only communication layer is through events.

However, large components are more complex to test, and when there are lots of mixins, it can be really hard to trace through the code, especially when advice is used liberally.

If you’ve got a lot of mixins, as we clearly do for our timelines, then you might be better breaking the component apart, into multiple components.

Our current timeline component is attached like this:

CustomTimeline('#timeline', options);

But there’s no reason why we couldn’t have done something like this:

CustomTimeline.attachTo('#timeline', options);
TimelinePagination.attachTo('#timeline', options);
TimestampUpdating.attachTo('#timeline', options);
TimelineActions.attachTo('#timeline', options);

Of course, we could attach those components within CustomTimeline:

function customTimelineMixins() {
  this.before('teardown', function() {
  this.after('initialise', function() {
    TimelinePagination.attachTo(this.$node, options);
    TimestampUpdating.attachTo(this.$node, options);
    TimelineActions.attachTo(this.$node, options);

However, as you can see, we have to be clever about handling our own teardowns here, which may not be worth the hassle.


If you’ve used mixins at all, you’ve likely encountered the default attribute conflict. If an attribute in declared in a mixin, it cannot be redeclared in your component, or even in another mixin. Our aim was to prevent unintentional ‘clobbering’ of methods and properties, where two mixins use the same property for different purposes, producing unexpected and hard-to-debug conflicts.

However, I’ve often wanted to avoid this guard, to give more specific default attributes for my mixins in my component definition. To do so, we can define a new method, “overrideDefaultAttrs”:

this.overrideDefaultAttrs = function(defaults) {
  utils.push(this.defaults, defaults, false) || (this.defaults = defaults);

This will behave exactly the same as the defaultAttrs method, but will pass “false” to utils.push, which will allow us to overwrite the attributes when conflicts arise.

It’s tempting to redefine defaultAttrs itself, but I think it’s better not to redefine the framework for future compatibility, and the guard may prove useful in other places. The method is also blocked from redefinition when being mixed in.

To add the method above, one could either add it to the global component base (be sure to do so before any components are defined):

define(['./base', './utils'], function(base, utils) {
  this.overrideDefaultAttrs = function(defaults) {
    utils.push(this.defaults, defaults, false) || (this.defaults = defaults);

Or simply create a mixin to be applied to each component as you need it.

We haven’t yet tried this in-house, but I think it would solve some readability and precedence issues.


Mixins have proved to be a vital part of Flight and twitter.com. Key learnings:

  • move your mixins to the start of the component definition
  • consider using overrideDefaultAttrs in component definitions
  • only use mixins where appropriate; use different components if you can
  • keep an eye on Flight for new features

2013: This year I have …

My annual End of Year update. See previous years: 2012201120102009 and 2008.

This year, we survived.

Yes, I know I said that last year. But it’s also how we feel. Exhausted.

Things are getting better. Our son is growing, learning new words every day. We might not have the sleeping situation sorted, but it’s still a fantastic feeling to have a family.

This year, we have also: bought a new car (my first new car), been to England for three weeks to see friends and family, been to Poland to see grandparents, moved out of San Francisco to a proper house in Walnut Creek with a garden, and endured the subsequent hundred-degree heat of the summer and the shivering freeze of winter.

At work, we’ve IPO’ed. Achievement unlocked. I’ve also switched from being a day-to-day coder to being an Engineering Manager, responsible for my team of six and twitter.com, the website. I’m still coding too. Well, deleting code. This year I deleted #NewTwitter.

We also got our Green Cards this year, so we can stay as long as we need.

At New Year’s, people make all sorts of resolutions and then fail to achieve them. This year, I’m going to take it easy on myself by listing antiresolutions. These are things that I would like to do, but not this year.

  • Run another marathon.
  • Do more programming after work.
  • Write a book.
  • Learn to play the piano. (long-standing antiresolution)
  • Buy another car.
  • Fly to England for a holiday.
  • Learn Polish.
  • Study for another degree.
  • Move house.

Wow, that feels better. What aren’t you doing this year?

Flying with atoddler

Catherine Webb recently pointed me to her outstanding 2008 post “Baby Holiday: SWAT Team special“. I felt it needed a little updating for the modern era. Here are our experiences from the summer. Not with a baby, but with a toddler.

If your toddler is under two, the airlines will try to force you to have the child on your lap the whole flight. Because your bollocks haven’t been kicked enough. However, you can call them and book a real seat. Well worth the extra cost.

If you read up on things, you’ll discover that you can bring your car seat. Be careful though – Virgin won’t let you bring a US car seat on the plane. They will let you check it and can give you a rickety leather seat of their own (reluctantly).

The reason why you want to bring the seat is so that you can have a belt he can’t escape from.

You’ll want to bring loads of baby stuff like food but remember the bastards at the security checks will have no sympathy for you. Low volumes of liquids in plastic bags only.

Once on board the plane, you may find the entertainment system doesn’t work in any of your seats. For eleven hours. Remember this is something of a nuisance for the cabin crew, who will become very unfriendly about it.

In the event of a trouser accident, the cabin crew will change the baby for you. Just press the button to ask them round and hand him over. It’s part of the cost of the flight, so insist if necessary.

Let me know how that goes.

Don’t expect toddler food for your toddler. Expect crap like crisps and sugar.

Don’t worry about the people in front, especially if they recline into your face the whole flight. Just smash and wallop their head. It’s payback time, and you have an excuse.

You can check a stroller at the door of the plane. But do remember to get it at the door when you get off, otherwise you can’t get back for it. It may also be at a different door, conveniently. The cabin crew will be oblivious to all of this so don’t worry them with it. They are probably very tired.

The simple solution to most woes is the iPad. Don’t leave home without it charged and loaded. Bring a few if you can.

Enjoy your flight. Chances are it will be mindnumbingly tedious. But, on the bright side, you’ll have a jetlagged toddler at the other end. Good luck with that.

Stories from New Zealand

I once went to New Zealand.


I was backpacking around the world, on my own, and landed in Aukland. I didn’t expect much – New Zealand is small, perhaps not geographically, but in terms of population. There’s only about 4 million of them.

There was actually a huge new modern hostel for backpackers there, called Auckland Central Backpackers. It was easily the nicest hostel I stayed in. Underneath was a club/bar sort of thing.

One night I was down drinking a few pints with a small crowd of fellow travellers. Some guys just finished up a karaoke song on stage, and passed us by. We laughed. Not actually because of them. We had complained about the noise at the start maybe, but you know, we’d moved on. We were laughing about something completely innocuous. However, one of those karaoke guys took offence.

At closing time, we left and found our karaoke friends again, who attacked us. The guy in front of me simply folded up after one punch. The other got into a protracted fistfight. After the bouncers had chased them off, we found him on the ground, his face smashed up horribly. Turned out they’d used knuckledusters.


I thought it was time to move on, and on a whim, went to a bike shop. On impulse, I bought a bike, a helmet, a speedometer, and a book of cycle trips.

The next day I decided to try out the new wheels. I set out for Auckland Harbour Bridge. It’s big. It’s famous. They do bungee jumps from it, so I knew there’d be a safe walkway.

I head for the bridge. As I take the last turn, it says “Motorway starts”.

I don’t turn back here, because the traffic is too busy. Besides, do they really have motorways here? It’s a tiny place.

And the sign is green, not blue. Blue means motorway. At least in the UK.

And anyway, I can always hop off onto the walkway if things get tricky.

Forty-five minutes later, I reach the other side and pull over in front of the waiting policeman, as the police car escorting me for the last third cruises off.

“What was that in aid of?” he says.
“Why, what do you mean?” I ask, all innocent.

It all got sorted out in the end, but it turns out that, yes, they have motorways, yes, the bridge is one, and no, they do not have a walkway of any kind.


At this point, I decide the leave the city. I decide to cycle the Northland for ten days. It’s all planned out in my book. Point to point. Hostel to hostel.

The first day went without a hitch. I got a train to the first hostel and cycled a few miles. Next day, I was doing fifty miles.

I woke early, filled my water bottle and headed out. It was a glorious cycle. I loved the exercise, since so much of travelling involves sitting around, or walking and gawping. Proper cycling is good for me.

After a few hours, I realised I was in trouble.

The bike was fine. It was me. I’d run out of water.

I wasn’t thirsty, but my legs had stopped working. I started walking the bike up the hills, and then just walking all the way. I was getting worried.

What do I do? Flag down a passing car? But there weren’t any! Do I look for streams? Can I suck water out of trees somehow?

Eventually I found a farmhouse, And, rather red-faced, I asked for some water. They obliged The next day I prepared better.


On the sixth day, I cycled across the top of some hills. It was really hard work, cycling at forty-five degrees into the cross-winds laced with rain. The only traffic were huge double logging trucks, always going too fast, too close. It was horrible.

Eventually I got to my stop, and got some bad news.

Firstly they were closed. Secondly, they were now a luxury retreat, not a hostel. Rooms cost $250, and that’s if they were open, which they were not. They said I should stay at the camp down the hill for $10, and called for me. But I had no tent or bed, so they wouldn’t let me camp.

I was in a pickle, and there was no way I was going back the way I’d come.

Luckily they caved, and let me stay. For the discounted rate of $200. And I have to say, it was pure luxury: sipping brandy from a large glass in front of the fire luxury. I slept well that night.


But not so well the next night.

I found the next hostel. But the sign had been painted over. This place had lost it’s International Youth Hostel mark. Hmm. And everywhere else was booked up. Hm. So I went in.

The manager emerged in a cloud of smoke. And not cigarette smoke. The more exotic kind.

I found the place inhabited by the homeless. By drunks. It was not pleasant. I got a single room anyway, and stressed about the twin beds in there. They wouldn’t sneak anyone else in would they? The room had a bad smell.

At about two am, I woke to find one of the oldest smelliest drunks, just lying next to my bed by the window. Watching me. He stank. I froze.

All night I froze, I wondered what to do. I fumed. I tried not the breathe. I was outraged. How could they do this?

As early as I could, I decided to just get out. Not stay for breakfast, for shower, nothing. Just get out, get away from this guy.

And that’s when the curtain moved, and he turned out to be just a shadow.


I’m sure there was more to New Zealand. Hobbits and scenery and beaches and huge trees.

But these are the stories I remember.

Orange robots

Bought a new Orange Pay-as-you-go SIM.
Stuck it in the phone.
Tried to add credit.

ME > 450 (send)

“Welcome to Orange. Press 1 if you’d like to top up.”

ME > 1

“If you’d like to top up with a credit or debit card, press 1, …”

ME > 1

“If you’re topping up with a voucher, press 1 now to return to the start. Otherwise, hold on.”

“Ok, let’s top you up. What’s your postcode. Just say the post code.”

ME > “E17 7QW”

“Ok. And the house number?”

ME > “47”

“Ok. I’ve got 47 Penumbra Avenue, London, E17 7QW. Is that right?”

ME > “Yes.”

“Ok. Now, what is your last name? Just say it out loud into the phone.”

ME > “Kufluk”

“CUTNER. Is that right?”

ME > “Well, no, it’s not likely to be right is it – you’re just a computer”

“Ok, let’s try again. What’s your last name?”


“CLARK. Is that right?”

ME > “NO!”

“Ok, well, I can’t figure this out, so I’m going to have to pass you to customer services.”

“Sorry, I can’t ocnnect you to customer services because you don’t have any credit. Calls cost 25p per minute.”

“Would you like to top up now?”
“If you’d like to top up with a credit or debit card, press 1, …”


I hang up.

When I called back later, I admitted to being Mr Elliot Clark. I confirmed that this was indeed the name on my credit card. I successfully added 20 pounds to my account.

To avoid confusion in future, I will be responding solely to this moniker. I would like to thank Orange for simplifying my affairs in this regard.