Show contents

What it’s like to work for Stripe

A company's culture is something intangible and nebulous, and yet it can be just as important to success as revenues or growth. Culture influences everything, from design and product implementation to the level of support and operations of a company. It's crucial to get it right.

I've been at Stripe for a few months now, and I've wanted to write about what it's like to work there. I've never been more impressed by the mechanics and culture of a startup. In fact, I've never seen anything quite like it.

Culture can be hard to define, and it certainly can't be created with mission statements and performance reviews. However, there are certain steps that founders can take to create an amazing place to work. With that in mind, I'd like to give you a taste of what it's like to work at Stripe.

Email - complete transparency

By convention, every email at Stripe is CC-ed to lists that go to either the entire company or to any particular team. This includes internal person-to-person correspondence. Our lists include dev, sys, office, product and support. From the internal wiki:

It turns out that Stripe generates a lot of email. In most cases, this is quite an intentional, positive thing — it's a great communication mechanism, persists forever, and is easily searchable. The reasons for CCing lists, is it's a really low-friction way to keep everyone in the loop, and that way people can jump in with helpful advice.

It's also a really good way to preserve openness as we grow (everyone still gets to see all the cool and important things that Stripe is up to) without requiring much extra effort.

This requires a lot of filtering, of course, but it allows me to dip in and out of the company's fire hose whenever I want. It gives every one of us a tremendous perspective and insight into what other people are working on, and a feeling of connectivity to the rest of the company.

I've never before seen this level of access or trust at a company. Other companies preach fearless communication. Stripe practices it.

There are a few other email conventions. For example, whenever a new substantial feature is shipped, an email goes around to the shipped mailing list from the people involved. I get a few of these every day, and they're often followed by a flurry of congratulations and gratitude from other teams.

All hands

Once a week, on every Tuesday, the company meets for an all hands. Each team explains what happened in the last week and what they're planning for the next. Again, this is all about transparency and communication.

At the end of the meeting we address FUD, or fear, uncertainty and doubt. Anyone can raise objections and discuss their concerns. The idea behind this, is that it prevents problems from staying hidden in one small part of the company, and makes sure everyone's thinking about how to solve the problems we have.

The is the only meeting that everyone is required to attend. Meetings are expensive, so during the week we try to limit them to as few as possible.

Group activities

When lunch arrives, an IRC bot (appropriately named nombot), announces the fact and the whole team relocates to the dining table. It's important that everyone gets together at least once a day, and meal times are a good excuse.

Aside from mealtimes, Stripe has a social list, and there are often after work drink-ups, BBQs and parties. For example, we all went to a local theater recently for a showing of The Dark Knight.

In addition to that, once or twice a year we organize company-wide hackathons: we all head together somewhere far away and just hack on new Stripe-related projects.

Everybody does support

Every single engineer does support, on a bi-weekly rotation. Even the founders John and Patrick. We provide support over an IRC channel, email, and through Stripe answers.

I've found providing support to be one of the best ways to learn about the company, how everything works internally, and our customer's needs. I've been writing a bunch of tools to automate some of the most common queries, like chargeback evidence, but at the end of the day we want to ensure that there's always a human available.

Hackathons & Capture the Flag

Every so often, Stripe has Hackathons. On a weekend, we invite a few hundred or so people around, break out a truckload of Ikea fold-up chairs, open up the office, order sandwiches, and hack on whatever comes to mind.

With Capture The Flag, we host a series of challenges that involve exploiting security holes. In our first contest, we had people ssh into specially configured EC2 servers. In the CTF this week, we're doing web vulnerabilities: CSRF, XSS, SQL injection and such.

I should stress that these are all independent initiatives from people inside the company. Anyone can come up with ideas like these and implement them.

IM & IRC

Google Chat and group IRC rooms are as integral as email to internal communication. Instead of meetings, we just do short chat conversations. Rather than constantly interrupt people's train of thought, we prefer to communicate asynchronously. Chat is often the happy medium between the latency of email, and the bother of in-person interruptions.

That said, sometimes it is much better to discuss things face to face. If someone hasn't got their headphones on, then it's totally acceptable to come over and ask them for five minutes of their time when they can spare it.

Also, an IRC bot messages me every six hours or so asking me to optionally reply with brief description of whatever I'm working on. It then displays what I wrote on some of our dashboards. This is rather useful, as it gives visibility at a company wide level into what everyone's doing.

Paper reading

Once a week, a group of us take a technical paper and discuss it over lunch. This week's was Characterization and Measurement of TCP Traversal through NATs and Firewalls, about TCP tunneling through firewalls. In previous weeks we've covered Bitcoins and C-Store. As someone who missed out on that side of university, I find these particularly interesting. Often the papers are from domains that I have absolutely no previous experience in.

Induction

New employees are asked to send in specifications for their “dream machine”, which is then built and waiting for them on their first day. It turns out that the average monitor size at a company is a good tell as to how much employers care about first-class equipment and, in turn, their employees. Stripe get this right.

For their first few days, new hires spend each day working with a different engineering group: product, systems, growth, ops, support. This is a great way to get familiar with what everyone at the company does, learn the codebase, meet everyone else, and make sure they can move freely across the company if they want to do so later.

People & teams

None of this would matter if Stripe didn't have fantastic people. Hiring well is the key to all of this, and people are the foundation of any company's culture. Frankly, I've never seen a team like Stripe's; we have the best people in the industry.

When you hire great people, you can afford to give them a lot of autonomy. Teams are made up of small numbers of people who propose ideas and then go off and implement them. There are no dedicated managers. So far, we have 31 employees. Each team is small and nimble, and there's a heavy focus on shipping quality software.

Lastly, people are encouraged to be generalists, and not to be afraid of exploring unfamiliar domains. I've been doing a bunch more work with servers recently, and Darragh, who usually runs ops, has fixed the dishwasher.

Patches welcome

Creating a great culture is key to an enjoyable working environment and ultimately, I believe, a successful company. It's a shame when that aspect gets blindsided in lieu of other parts of the business, an all too common occurrence.

We've learned a few things about cultivating culture at Stripe, and we're constantly experimenting and evolving. I feel incredibly fortunate to work in such a place, and I'm hoping this piece will be useful for people who want to create a similar environment.

 
3,250
Kudos

Go

Go is a super simple Sinatra URL shortener for use behind the firewall.

Most companies soon start to build up a fair number of internal URLs, and it can often be tricky remembering these all. This especially problematic when somebody new joins the company.

Go is a simple solution to this problem. Once installed you could point http://go/wiki, for example, to your company's internal wiki.

Features:

Go and give it a whirl!

Go

 
361
Kudos

A JavaScript Security Flaw

The following is a JavaScript security flaw:

<script>
  var str = "</script><script>alert('Pwned');</script>";
</script>

Don't believe me? Try it for yourself. The browser ignores the fact that the <script> tags are inside a JavaScript String, invoking the alert() function.

The reason for this odd behavior is that the page gets rendered in various stages. First the HTML is parsed, and a render tree created. Only then, is the JavaScript actually executed. In the example above, the render tree see the <script> tags, and is oblivious to the fact that they're inside a string; it has no concept of JavaScript. It strips these out, and evaluates the script nodes as usual with our injected message.

This behavior would be little more than a curiosity, were it not for the common pattern of injecting JSON into documents, say with ERB.

<script>
  var users = <%= @users.to_json.html_safe %>;
</script>

If you have the line above anywhere in your code, and @users includes some user submitted data, your application is vulnerable to a XSS attack.

If you're using Rails, you can thwart this vulnerability by setting ActiveSupport.escape_html_entities_in_json to true. The default is false.

 
913
Kudos

An Asynchronous Image Uploading Interface for Svbtle

For the past few months, I've been using Svbtle, Dustin Curtis' blogging platform. The key theme running throughout the service is minimalism, and if Svbtle is designed correctly, then the interface should fade away. Content is everything. However, Svbtle originally lacked a photo uploading interface, and Dustin was hesitant to add one that didn't fit with the design philosophy. So I wrote one that is asynchronous and adds no visual UI.

Svbtle’s editing interface is incredibly straightforward; all you see is the text you’re crafting. Articles are written in Markdown, so no formatting controls or complex WYSIWYG editors need to be involved. It’s the simplest possible thing.

Svbtle

However, this makes designing an image upload interface tricky. Where should the browse button be, the file dialog and the upload progress? How could this feature be implemented without cluttering up the interface?

When I was looking at the problem, I decided to take a step back and think about what I'd want from an end user perspective. One of the worst experiences is browsing for a file, and waiting for it to be uploaded. I wanted to avoid that at all cost. Ultimately, as a writer, I just want to drag an image onto the text and have everything else handled behind the scenes.

Fortunately, in modern browsers, it's incredibly easy to do something like that using HTML5. First we just need to listen to drop events when files are dragged onto the browser. Then we can upload them in the background using Ajax.

The Implementation

Let's have a look at the actual implementation in JavaScript. Before we can even bind to drop events, we need to cancel the dragenter, dragover and dragleave events (I won't even try to explain why the spec requires that). To do that I've written a simple plugin for jQuery, called jquery.drop.js.

Next we need to iterate over the dataTransfer.files array, calling our upload function.

$('body').dropArea();

$('body').bind('drop', function(e){
  e.preventDefault();
  e = e.originalEvent;

  var files = e.dataTransfer.files;

  for (var i=0; i < files.length; i++) {
    // Only upload images
    if (/image/.test(files[i].type)) {
      createAttachment(files[i]);
    }
  };
});

So far so good. Now we actually need to implement the createAttachment() function. The secret sauce in this function is generating the client-side GUID. This will be sent along with the upload to the server, stored in the database, and used whenever we need to generate a URL to the upload.

The fact that we're generating a GUID on the client-side means we can use it immediately to generate a URL for that image, inserting the markdown tags straight into the editor. We don't have to wait for the upload to finish to retrieve the database-generated ID. To the user, it seems like the image has been uploaded instantly, and it doesn't block their writing.

Next we're using the little known FormData constructor here. This lets us do multipart uploads without having to deal with boundaries and binary encoding, it'll do all of that behind the scenes. For this to work seamlessly with jQuery, we need to disable the contentType and processData options.

var createAttachment = function(file) {
  var uid  = [App.username, (new Date).getTime(), 'raw'].join('-');

  var data = new FormData();

  data.append('attachment[name]', file.name);
  data.append('attachment[file]', file);
  data.append('attachment[uid]',  uid);

  $.ajax({
    url: '/attachments',
    data: data,
    cache: false,
    contentType: false,
    processData: false,
    type: 'POST',
  }).error(function(){
    // ...
  });

  var absText = '![' file.name + '](/attachments/' + uid + ')';
  $('.new_post_area').insertAtCaret(absText);
};

Finally we're inserting the image markdown tags into the page using the insertAtCaret() function. This too is a custom jQuery plugin called jquery.insert.js. It'll make sure that any text inserted is placed after the blinking caret.

So that’s how we implemented image uploading on Svbtle. It contains no additional visual interface, and it functions completely asynchronously, without blocking the writer. It works like a charm; you simply drag the image onto the page and then continue on writing. The file is uploaded in the background, and by the time the article is written, all the transfers will have finished.

 
1,209
Kudos

The State of Hiring

Imagine going on a first date, and immediately proposing. That's hiring in a nutshell. Companies have to make long-term and far reaching decisions about candidates based on very little data and time. Of course, the same is true in the opposite direction too.

At most companies I've witnessed, it's clear to say the whole hiring process could vastly improve. I see candidates who I know are amazing programmers being failed at the phone interview, and often less able engineers cruising through with flying colors.

For example, here's a conversation I had the other day:

Bert - “That last candidate didn't do very well, he flunked my Poisoned Chalice question.”
Me - “Your what?”
Bert - “Yeah, the Poisoned Chalice question. He totally chose the wrong cup.”
Me - “Oh dear”

Are we the only industry that asks entirely irrelevant questions during interviews? I mean, if the guy is interviewing for a front-end programming job, is it such a stretch to ask him about programming? And frankly, when has anybody ever programmed on a whiteboard?

Perhaps the whole process is fundamentally flawed though. I've certainly made my share of mistakes, and it's incredibly hard to evaluate someone in such a short period.

The fact is, we don't have to model the way we structure our interviews on other professions. We don't have to make arbitrary judgements based on half an hour out of a busy day. Often, we can ascertain a programmer's ability through their portfolio of open source work. Alternatively, we can set simple and practical coding challenges.

This approach gives you so much more information on which to base a judgement on. You can see if the code is well written, correctly structured and properly tested. Then, your interview becomes much simpler. All you have to do is make sure the candidate actually wrote the code, and check for a cultural fit.

There's another alternative too. Companies like Automattic (WordPress) require a one month no-obligation trial before any new employee is officially hired. This works for them, but can have its downsides too. The lack of commitment on the company's behalf may deter potential candidates. This is clearly a cost Automattic is willing to take though, as making the right hiring decisions is so important.

So the jury is still out on how to improve the hiring process. What I do know though, is that the conventional system is broken, and is well due an overhaul.

 
353
Kudos

Here’s to the Misfits

The school I went to in England used to proudly display their famous alumni in black and white photos circling the theatre lobby. From John le Carré, to John Cleese, the list included notable actors, top politicians and accomplished actors. What the school didn't tell admiring visitors though, is that the vast majority of those famous alumni had been expelled. They were misfits, and the system couldn't cater to them.

In Ken Robinson's TED talk about education and creativity, he mentions the story of Gillian Lynne.

When she was at school, Gillian was often disruptive and couldn't sit still. The school wrote to her parents, and said she had a learning disorder. So her mother took her to this specialist to explore treatment options.

After this doctor had talked to her mother for twenty minutes, while Gillian sat patiently sitting on her hands, he told her to wait while he went outside to talk privately with her mother. As he left, he turned on the radio sitting on his desk.

When the pair were outside, the doctor turns to Gillian's mother and says: 'watch her'. For as soon as they had left, the little girl was up and moving to the music. They watched for a few minutes, and eventually the doctor turned to her mother and said: “Mrs Lynne, your daughter isn't sick, she's a dancer. Take her to a dance school.”.

Her mother followed the doctor's advice, and Gillian flourished. She became a ballerina, a choreographer and was responsible for producing some of the greatest shows of our time, such as Cats and the Phantom of the Opera. A different doctor might have put her on medication and told her to calm down.

By definition, the system isn't set up to cater to misfits. While I am by no means comparable to those famous alumni on my school wall, I am also a misfit. Misfits don't blend into the artificial world of enforced hierarchies, such as those in high school, and are often happier forging their own paths. By the time I was seventeen, I had already dropped out of two schools and decided enough was enough. The system wasn't for me. I packed up my bags and moved to London. I knew what I was passionate about, and I wasn't afraid to admit it. I wanted to spend the rest of my life programming.

Chris Sacca recently gave the commencement speech to a crowd of newly graduated students. He talked about being a misfit, about standing out and embracing what you really are. As he says, your GPA only matters to people who can't find any other reason to find you interesting.

The most important piece of advice I can give you on the path to happiness, is not just be yourself, but be your weird self. It takes too much energy to be other than your weird self. We spend so much of our lives living up to the expectations of others.

It's our collection of screw ups, stories and idiosyncrasies, that make us weird and interesting. Weirdness is why we adore our friends. Weirdness is what binds us to our colleagues. Weirdness is what sets us apart and gets us hired. Be your unapologetic weird selves.

So here's to the misfits, the rebels and troublemakers. The round pegs in the square holes. You can quote them, disagree with them, glorify or vilify them. About the only thing you can’t do is ignore them. Because they change the world.

 
1,030
Kudos

Killing a library

A programming library's main mission should be to make itself redundant, and with that in mind that I'm announcing the deprecation of Juggernaut.

Juggernaut was one of the first solutions to pushing data in realtime to clients; at first it was using Flash XMLSockets, and then it moved to WebSockets when they were widely available. This sort of technology has lots of interesting applications, such as chat, realtime collaboration and games.

It was also my first open source library, written back when I was still in high school. At the time, it had a fair amount of press and gained some popularity. Indeed releasing Juggernaut led directly to my first job, dropping out of school and moving to London.

So why am I killing Juggernaut? Well, it's because of the little known HTML5 Server-Sent Events (SSEs). This is a browser API that lets you keep open a socket to your server, subscribing to a stream of updates. It's perfect for the use-case Juggernaut was created for, and what's more can be implemented in a few lines of Ruby. In other words, it makes Juggernaut completely redundant.

On the client side, all that is required is instantiation of a EventSource object, which you can pass an endpoint. For example:

var source = new EventSource('/stream');
source.addEventListener('message', function(e){
  console.log('Received a message:', e.data);
});

When the stream connects, the open event is triggered, and whenever a new message is received, the message event triggers.

Sinatra actually includes an example chat using Server-Sent events. Consuming EventSource connections is as simple as responding to clients with a text/event-stream content type and keeping the connection open:

get '/stream', :provides => 'text/event-stream' do
  stream :keep_open do |out|
    connections << out
    out.callback { connections.delete(out) }
  end
end

Transmitting messages to clients is just as straightforward. Frankly, I wish the people behind WebSockets overly-complex protocol had taken a similar approach.

post '/' do
  connections.each { |out| out << "data: #{params[:msg]}\n\n" }
  204 # response without entity body
end

In other words, all messages start with data:, then the message body and finally a double new line. In addition to data messages, there are a variety of other supported ones, such as a retry timeout and setting an event name. See the specification for more details.

Browser support for SSEs is actually pretty good. Chrome, Safari, Firefox and Opera all support them, with IE being the usual black sheep of the family. However, there are a variety of polyfills out there, so adding support for older browsers is trivial.

Juggernaut seamlessly integrated into backends like Rails and Flask using Redis' pubsub, and we can do the same integration with SSEs. Here's an example of transmitting all events on a pubsub channel to clients, and here's one where clients can subscribe to specific private channels.

So six years after Juggernaut was first released, it has now been made redundant by functionality that is baked into browsers. What's more, SSE support can be implemented in a couple of lines of Ruby. These are exciting times indeed!

 
1,256
Kudos

A browser API for one click payments

TLDR: A JavaScript API to access the browser's autocomplete data, allowing one-click signups and purchases.

In the early 1900s, when stagecoaches were first being converted into automobiles, the engineers were so entrenched by existing coach design that they positioned the driver on the outside of the car. Some models went as as far as putting fake horses on the front, their eyes containing lamps, their mouths incorporating horns, and the torso housing fuel, tools and spare tires.

Horseless Carriages

I feel that auto-completing forms are much like those 'Horseless Carriages', a solution to a specific problem and not the wider picture. What if we removed the forms altogether?

I'm proposing a JavaScript API that lets us fetch autocomplete data that's already stored in the browser, such as name, address and credit cards. This means that a site's checkout flow consists of two steps: clicking 'purchase' and authorizing the domain's access to the relevant data.

requestProfile

It's not just payments that could be streamlined, but signups too. Sites could check to see if the API was supported and, if not, display the usual signup form. The fact that this process is now streamlined means it's likely to increase conversion rates.

The API is extremely simple, consisting of one call to navigator.requestProfile, passing an array of requested data types and a callback function.

navigator.requestProfile(['firstName', 'email', 'cardNumber'], function(profile){
  console.log('Your name is:', profile.firstName);

  /* ... */
});

I've created a proof of concept Chrome extension that implements the API, and allows sites access to pre-configured data stored in the browser.

There are a number of things I want to improve over this initial implementation, such as making the permissions dialog modal, encrypting credit card numbers and displaying previews of any data that was going to be shared with the page. However, I feel it's a good starting point.

Getting the security considerations right is key to making this work. As browsers already store (and encrypt) credit card data, I feel that aspect is less of an issue. Rather, it's more of a usability concern, as people tend to blindly authorize permissions. Perhaps the answer is requiring the card's CVC, or a countdown forcing users to read the infobar.

I've also started a discussion on the public-webapps list. If this is something you'd like to see in the browser, or want to weigh in on, by all means share your thoughts. Together we can improve the status quo!

 
595
Kudos

Catapult

One of the benefits of building stateful client-side apps, is that you can make them independent from the rest of your backend, having a separate repository and deploy process. The advantages of this is that it keeps your backend and frontend decoupled, and was the principal point behind my article on using Rails as an API.

However, splitting JavaScript, CoffeeScript and CSS out from a Rails app can be tricky. You no longer have an automatic asset pipeline and compilation, or indeed a server.

I've been using a number of basic Rack scripts to manage my JavaScript projects, and recently bundled them up into a gem called Catapult. Catapult manages building new apps, compiling assets and serving them. The gem is built on-top of Sprockets, and comes with CoffeeScript, Stylus and CommonJS compilers out of the box, my usual work flow.

To be fair, there's no shortage of asset compilation libraries on GitHub, and I was a bit loath to reinvent the wheel. Having said that, the key principal behind Catapult is simplicity. It's suits my personal use-case perfectly, and customizing it is absolutely trivial.

Now let's explore some basic usage. To generate an app, use the new command:

$ catapult new myapp

  create  myapp
  create  myapp/assets/javascripts/app.js
  create  myapp/assets/stylesheets/app.css
  create  myapp/browser.json
  create  myapp/public/index.htm

$ cd myapp

Now you can start a catapult server:

$ catapult server

And open up the app in your browser. During deployment, you'll want to serve the files statically. You can write compiled files to disk using the build command.

$ catapult build

You can even watch the files for changes, and then automatically build:

$ catapult watch

As I say, the source is incredibly simple. In the spirit of @fat's talk on documentation, I invite you to dive in.

 
182
Kudos

The Power of Language

Every now and again, you learn something new that challenges your basic assumptions about the world. This happened to me the other day as I was reading Aatish Bhatia's article on colors. What's quite fascinating, is that the majority of the world's languages don't make a distinction between the colors green and blue.

In other words, they do not have separate terms for green and blue, instead using a cover for both. For example, green traffic lights in Japan are referred to as blue (青). The Korean word 푸르다 (pureuda) can mean either green or blue. Indeed, the Vietnamese don't distinguish between the color of leaves and the color of the sky.

In fact, other languages have words for colors that we don't distinguise between in English. The Russians have two words goluboj (голубой) and sinij (синий), which mean light blue and dark blue. They are just as baffled that we refer to them as a single color.

It turns out that just by having words for green and blue makes the perceived difference between the two more vivid (with some caveats). The different names of colors fundamentally changes how we perceive the world. When infants start learning color names, their whole brains rewire themselves, and their ability to distinguish colors transforms.

However, it's not just words that mold your mind, but the language constructs themselves. For example, just having a gender system in a language dramatically effects the feelings and associations speakers have towards objects around them. Several physiological experiments in the 1990s demonstrated gender's influence; subjects perceived masculine words with manly traits, and feminine words with more womanly attributes.

A language's gender even personifies itself in art in the way that abstract entities, such as love and death are presented. For example, German painters are more likely to paint death as a man, whereas Russian painters are more likely to paint death as a woman. Such influences run deep within our culture, and we often aren't aware of them.

In 1770, as Captain Cook was first exploring Australia, his men came across a small tribe called the Guugu Yimithirr. After various interactions with the tribe, they discovered an astounding thing: whenever these aborigines referenced a direction such as left or right, they would so in terms of points of the compass, such as east or west. They had no words denoting egocentric directions in their language, instead exclusively using cardinal directions.

What was even more interesting though, was that by embedding geographical directions into a language, speakers seemed to have an uncanny sense of direction. Regardless of their surroundings or conditions, whether indoors or outdoors, they always knew where north was. Indeed, whenever the Guugu Yimithirr recalled a situation, they always did so in terms of their direction at the time. To put it another way, geographical locations were embedded in their memories.

Language is critical for higher level thought too. We 'think' in a language. For example, infants don't have spacial awareness, or understand how objects can be relative to each other, until they learn the words for describing relativity. Indeed deaf children, who aren't taught sign language, are often significantly mentally handicapped.

So, not only does the language you know literally change your vision, it's also fundamental to everything we think or do. Language might well be the greatest invention mankind has ever come up with.


References:

  1. Life without language
  2. How deaf people think
  3. How does our language shape the way we think?
  4. Anchoring, Iconicity, and Orientation in Guugu Yimithirr Pointing Gestures
  5. Language and Cognition: The Cognitive Consequences of Spatial Description in Guugu Yimithirr
  6. Does Your Language Shape How You Think?
 
520
Kudos