Retaining Engineering Talent

by Dan DeMeyere - @dandemeyere

Retaining engineering talent has become an increasingly challenging task for any engineering manager in the Bay Area. Engineers have a lot of power in the current market and, as a result, it’s easy for engineers to leave and find a new position elsewhere. Hiring and onboarding new engineers are time consuming and expensive. A team that can mitigate turnover is a more productive and efficient team.

thredUP has been very fortunate regarding engineering retention. Our largest team, Web Engineering, has twelve engineers. In the past 3.5 years only one person has left in order to pursue a passion project after working with us for over five years. While luck may play a role, much of the credit for our great retention goes to the team. The culture they have built, the thoughtfulness that goes into the hiring process, and an emphasis on peer mentoring has helped keep engineers at thredUP. Even so, retention is still something I have to constantly focus on as an engineering manager.

For me, the first step in retention is identifying the motivating factors for every engineer. Is the engineer someone who loves the company and our mission? Is the engineer motivated by what they do professionally and the projects they work on? Is the engineer primarily motivated by money? These motivators are not mutually exclusive and therefore every engineer should be managed in a way that is tailored to their specific mix of motivators.

Next, I try to develop a mutually beneficial relationship that aligns the company’s objectives with the engineer’s desired career path. At thredUP we call this relationship “professional development”, and it has been a big priority for us as a company. It’s the reason why I’m in the position I’m in today and it plays an important role in our ability to retain talent.

As my manager does with me, I meet with my engineers frequently to discuss professional development. To facilitate opportunities for personal and professional growth for engineers while delivering on the company’s objectives requires a thorough understanding of every engineer's desired career path. This is why communication is key to retention because it ensures that the needs of both the engineer and the company are met.

Once I know what kind of opportunities will motivate engineers, we work together to build a roadmap. This step can be a challenging endeavor and it requires thoughtful planning, but thankfully there's a great book, The Alliance, that provides a framework for how to structure these professional development roadmaps.

The Alliance identifies different “tours of duty” an employee/employer can embark on based on the motivators of the employee. For example, an early employee or engineer that identifies personally with the company's mission will be well suited for a "foundational tour". This is a long-term tour focused on improving an employee's ability to provide maximum value for the company.

If an engineer is more motivated by following a desired career path, for example becoming an engineering manager or a technical lead, then they would be more suited to the “transformational tour”. In these cases, developing a roadmap is as simple as determining where the engineer is now, where they want to go, and what milestones lie in between. Once you attach timelines to each milestone, the relationship for this tour becomes a transparent series of check-ins discussing where they are at in the current milestone and how I can help them get to the next one.

Of all of the tours listed in The Alliance, the “rotational tour” is the one I use most often. Engineers looking to learn new technologies, solve difficult problems, and deepen their technical skill-sets tend to thrive when they’re able to rotate through big projects that expose them to the technical opportunities they’re looking for. The hardest part of this type of tour is aligning projects that serve both the company's objectives and engineer's professional desires. I work very closely with our product team (feature roadmap) and our CTO (technical roadmap) to discover and align these opportunities as early in the process as possible.

Sometimes opportunities for engineers fall into place effortlessly and other times you have to work hard to facilitate the opportunities engineers are looking for. At the end of the day, the more effort and energy you invest in professional development, the more the team will yield in terms of retention, motivation, and job satisfaction.

Asynchronous Slack Scrum

by Dan DeMeyere - @dandemeyere

For the past four years, we've done scrum the same way. Standing up at 9am sharp.

Our scrum is straightforward. What were you working on yesterday? What are you working on today? Are there any changes to plans or intersecting efforts that should be discussed?

When we were small, this worked great. As we grew, we needed to tighten up our scrum updates to keep scrum an efficient use of everyone's time. Then our web and mobile teams started participating in a combined scrum so we had to make our updates even more concise. Around this time we also made a decision to save any tangents or questions for after scrum to make sure we weren't wasting a large portion of the team's time while two engineers went into the weeds on something.

At fifteen engineers, we were still under 10 minutes, but one engineer keenly asked recently:

Everyone just gives a brief, high-level update of what they're working on, but we all know what projects everyone is on. Isn't the point to surface those issues so we can go into the weeds? How am I supposed to remember my questions I want to follow-up on while I'm supposed to be paying attention to everyone else's updates? At this point, what is the value add of scrum?

These questions made it obvious that our scrum was no longer serving its intended purpose. It was hard to believe that a process we did every day for so long had been broken and we didn't know about it.

So we ran a little experiment. We created a new Slack room for scrum. Every day, before or at 9am, everyone posted their scrum update. The new guidelines were to not worry about brevity or being too deep in the weeds. Scrum updates are now opt-in in terms of who reads what so you won't waste another engineers' time with specificity. Say what needs to be said to inform teammates with what they need to know about your efforts for your project.

We ran the experiment for a week and voted anonymously during our next sprint retrospective whether we wanted to continue doing scrum in Slack. The vote was unanimously in favor of Slack scrum. The purpose of scrum was restored and the team was in full support of the process change.

In addition to fixing scrum, we also discovered that our new Slack-based scrum yielded new value for the team.

Evergreen

When someone misses stand-up scrum or someone is on vacation, there's no way for them to know what everyone said during scrum. With Slack and its evergreen nature, you can now go on vacation for a month and be able to catch up on what the team has been up to in a matter of minutes.

Having this visible history of scrum also results in increased accountability. When you get ready to post your scrum update, yesterday's update is still in view. It can act as a helpful prioritization tool to see what you said you would accomplish the previous day when you're getting ready to prioritize your efforts for your upcoming day.

Working Asynchronously

Stand-up scrum is synchronous in nature — only one scrum update or conversation is occurring at any one point in time. While some companies like GitHub intentionally gear their processes to be asynchronous, we sort of fell into it serendipitously with our new scrum format.

Having an asynchronous scrum has multiple advantages. For one, we no longer have a forced interruption every morning. If someone wants to come in early and get a head start, they can post their scrum update and check back to see the rest of the team's update once they come up for a breather.

If someone posts a scrum update that you want to follow up on, you don't have to worry about de-railing stand-up scrum with a question. You can spin up a separate Slack thread and dive into the details without stopping scrum or wasting anyone else's time.

To play devil's advocate, there are some downsides to asynchronous Slack scrum. For one, if you're not on a project with someone, it's possible to go days without face-to-face interaction with them. Over time I could see this being a morale issue. Stand-up scrum can also be a nice kickstart energy-wise to the day so this is something we'll be keeping a close eye on as well.

Revisiting our agile processes is something we do regularly through sprint retrospective. Typically the catalyst for process change is an inefficiency surfaced by the team, which was the case for scrum, but we'll be taking a new angle on this in the future. How can Slack and other technologies that have become engrained into the way we work help evolve our processes to be more efficient and yield more value?

A CTO's Notes & Musings From F8

By Chris Homer - @chrishomer


I was at F8 today and thought I might as well flush out my notes and post them here instead of buried in evernote.  

Overall, solid day at a conference.  My general take on it is that it is more of a "Product Manager's" conference than a developer's conference.  Still very interesting but no hackathon, no labs, little code level talk in sessions.  Of course at an early stage company, the lines blur and even at thredUP there are aspects of my job that fit closer with Product than engineering.  That said, the announcements and topics were thought provoking and what follows are my notes built out with some additional "musings".

Keynote

Zuck kicked things off with a review of the last year and some announcement "hints" before handing it off to others to talk Messenger & Parse.  The most impactful part of his talk was his discussion about bugs.  Bugs are something that every startup has to deal with.  Moving fast enough to "figure it out" almost always means you leave a trail of debris behind you.  Sometimes you can clean it up, sometimes you can't.  Until the last few years, Facebook has allowed many bugs to fester.  Last year they committed to reaching a 48 hour resolution on all "major bugs".  They hit that.  This year they are committing to resolving 90% of ALL BUGS within 30 days.  This is great to hear and quite inspiring.  One of the crucial aspects of this commitment is their willingness to be completely open about their progress against this goal.  Their system reports the status publicly and I love it.  Wondering how we can work towards the same at thredUP.  Not necessarily publicly, but fully visible to everyone at the company and something we are much more conscious of and held to. 

The Celebrity Sighting

While over checking out the Oculus demo area, I turned to my left and there was a "posse" plowing past me towards the "teleport" demo.  At the head of the pack was the 5' 9" curly haired mogul (zuck) with about 25 people in tow.  I was struck by how it reminded me of a similar scene when I was at Microsoft and Bill Gates showed up at six flags during a company party.  Pretty entertaining to watch actually, but it was also instructive - his poise and confidence was palpable.  He was CLEARLY in charge and had everyone hanging on each word and move.  

Session 1: Parse

I have been spending a lot of time thinking about our systems and our architecture at thredUP.  The path we are on is generally towards a micro-services infrastructure but it's a long-term evolution.  Something I like to ask myself is, "what are the alternatives we haven't considered?".  Parse seems to provide a new alternative.  While I could never see our entire company and app on parse, I could certainly see how 90+% of the shopping experience could be driven through a backend built on Parse.  Today it's a Ruby on Rails app/API slowly moving towards a more thoughtful API structure.  However, were I to embark on the project today, I would definitely consider Parse for a good chunk.  Turning over server infrastructure and much of the boilerplate backend is appealing as it focuses your attention on the value-add for your application rather than reinventing what Facebook/Parse has solved.

The announcements from Parse included better Internet of Things support, some developer tools updates and integration into React.  The React integration was the most intriguing to me.  At thredUP, we are investing serious time and energy in planning a rebuild of our Ecommerce Customer Experience.  For the web application, we have chosen to go with NodeJS & React.  What Parse announced today is a plugin for React so that instead of building out the full Flux pattern, you delegate the dispatcher and stores to the plugin and Parse.  At first it seemed to violate everything that I love about Flux.  But then I began to see the simplification it introduced and I think it's worth a look.  If nothing else, it probably provides a good example of a way to abstract away the boilerplate of Flux.  Reflux, Fluxible and others do this too, but none are simple and they are in fact very complex.

Session 2: Facebook Login & Graph Updates

This session was interesting but only a few things of note from my perspective:

Direct Support - Facebook is introducing a 1:1 chat support service with developers on staff.  They have opened this up to anyone at F8 with 6 months free.  Going to try this out.

Login Manager - With the updates to the SDK comes a new component that seems to abstract away some of the complexity of dealing with sessions and authentication in iOS and Android apps.  Pretty interesting an worthy of time.  

user_posts permission - Looks like you will be able to request permission to dig into a users news feed and related graph nodes/edges.  Pretty interesting and powerful.  I could definitely see value to crunching it for things like sentiment analysis, pro-active CS engagement, and interests & recommendations.

Providing a Great Login Experience - this was the most valuable topic I thought.  They talked about the practice of "requiring" permissions and how it sours the user experience.  Some may be truly required, but usually they are not.  They also talked about how low the "decline" rates are with permissions and how it's not worth hard requires that block the user from proceeding.  The framework they discussed for designing a login flow was "Value, Respect, Reliable".  Value refers to communicating the value of sharing your information and they used Shazam as the example.  Respect refers to being respectful of you users' right to privacy and allowing them an experience while they "get to know" your app/company/service.  Reliability refers to the testing and thorough work put into your flow - if it's not bug-free, intuitive and fast, it's a big problem.  None of this is rocket science, but was a good reminder that this is the first impression you have with new users, make it count.

Session 3: Facebook Messenger

The session itself was a little disappointing. I was expecting more out of it and it was just kind of "ok".  There were some promising nuggets and food for thought in the broader announcements around messenger as a platform and messenger for business.

Messenger as a platform - the big thing here is sharing through messenger and allowing a conversation to take place from your app, through messenger and then back to your app.  I am not sure what this means for thredUP yet but some thoughts come to mind around "shopping with your friends", "building outfits for your friends", "gift lists" etc.

Messenger for business - this is the bigger opportunity I think.  It's early days but the gist of it is that a user could ask that we send a receipt to messenger for them.  This would deliver their receipt to their phone or to their inbox on facebook.  The user could then reply right there to ask questions or get help.  In addition, we could provide real-time fulfillment and shipping updates along the way and possibly ask for feedback post purchase.  They are currently focused on the after-sale experience but I would love to explore integrating with them in pre-sales for live onsite chat and maybe even co-browsing assistance.

Oculus

No real business application here yet - unless someone wants to hack on a 3D immersive shopping experience with Unity :)

But, the new demo - codenamed "Crescent Bay" was AMAZING.  I would love to set that up in the office in one of our conference rooms.  It was so completely immersive and it almost felt real.  There were times where I wanted to reach out and touch what I saw and in one scene with bullets, explosions and shrapnel flying in slow motion, I felt like I was in the matrix and needed to start dodging bullets.  Can't wait for it's release.

 

Responsys API Ruby Gem

by Dan DeMeyere, Morgan Griggs, and Florian Lorrain

In the past year, thredUP's email marketing team has elevated their game to the next level. While they increased the frequency of their campaign cadence, they actually sent less emails per customer as a result of careful audience segmentation and campaign personalization. To segment and personalize in a way that would make our emails resonate more with our customers, our email marketing team had to analyze customer data via Looker (our business intelligence tool) and then upload lists for individual campaigns, which was a laborious and tedious process. This is something that we hoped our current email service provider (ESP) would have been capable of, but after more than a year of doing workarounds like this, our team arrived at the conclusion that we needed to find an ESP that empowered us instead of getting in our way.

Our CTO led discussions with a number of ESPs and ultimately decided on Oracle's Responsys solution. After the contract was signed, the integration project came down the pike to our web engineering team.

Our first step was getting to know our current ESP integration inside and out. Anyone who has completed an ESP migration before (this wasn't our first ESP migration rodeo at thredUP) knows that you can't just flip one ESP switch off and another ESP switch on. To warm up the new ESP's IP addresses, you have to integrate the new ESP into your existing system and ensure data is reconciled across all platforms. For example, if someone unsubscribes on your existing ESP, you need to update your web application's records as well as your new ESP's records to prevent sending someone an email in one system that already unsubscribed in a different system.

Once we had a feel for the existing endpoints, flows, and system dependencies, we had the necessary context for the next phase of the project, which was the research phase. Before doing a deep dive, we did a high level walkthrough to understand how we would be interacting with Responsys (ex: JSON? XML? SOAP?), how Responsys differed from our existing ESP and what terminology we should formalize to avoid confusion while discussing the Responsys API.

Responsys has a robust set of functionalities and along with it, they have a robust set of documentation. Since our team for the project was relatively small (3 engineers), we decided to divide and conquer. We divvied up the major components (profile extensions, list management, etc.) such that the team in aggregate had a thorough understanding of every major component. When someone felt they fully understood one of the components they were responsible for, they would do a mini presentation to the other two engineers. After 3 days (1 day for high-level, 2 days for deep dive), we were ready to start breaking down the project so we could get to work.

At this point, we did what most Rails engineers would do:

Every link was a dead end. Gems that didn't work anymore. Gems that were abandoned. We went multiple pages deep sifting through results and we tried every gem or library we could get our hands on. Nothing worked. With no viable gem options, we decided it was time for an architecture planning session.

Do we build our own Responsys gem? Do we create a self-contained layer in our app that talks directly to the Responsys API? Because our current ESP contract was expiring in less than a month, our project had a deadline. If we didn't complete the integration by the deadline, we would have to re-up our contract with our existing ESP and unfortunately they don't do month-to-month.

We couldn't afford to go down one road for a week or two and turn around once we discovered it was the wrong choice. We knew building the gem was the right way, but we didn't know if we could pull it off in time. We decided to have one person prototype the gem and one person prototype the non-abstracted internal approach. We time boxed the prototyping to one day and scheduled time to huddle the next morning.

The next morning we reviewed both prototypes and while the internal approach was further along, the gem was at a point where it was a viable option. We knew the gem would be more work and we knew we would have to be more thoughtful with decisions to ensure the gem was abstracted to the point where anyone could use it for their company, but we decided to bite the bullet and go for it. 

We spent the next day or two deciding on how to organize the gem code, what naming conventions we should use (we decided to use the same terminology in the Responsys documentation) and what gem functionality would be required to complete the migration project. Until our project was complete, we wanted to focus our efforts on gem functionality that our web app required.

Once we identified the critical path for the project, we made sure the gem was always one to two steps ahead of the web app's integration. We huddled briefly every day to give updates and determine whether we needed to shift the team's resources around so that we could always be going full steam ahead on our web app's integration. 

I'm happy to say we completed the project on time and that deciding to build the gem was the right decision: https://github.com/dandemeyere/responsys-api

We still plan to add more functionality to it as well as tighten up the documentation, but we've started what we think is a great base for ourselves and others to build upon. We've already had the fine folks on the TaskRabbit engineering team open pull requests to help improve the gem and we hope this post will be a catalyst for others to join the project as well.

Operations Engineering @ ThredUP

By Syed Usamah

At ThredUp, our engineers are broadly divided between three teams: Mobile, Web Engineering, and Operations Engineering. In this post, I am going to talk mainly about what we do here as operation engineers.

ThredUp is a very operations-centric business, and the Ops Engineering team plays the vital role of providing the systems, tools, and the analysis required to make the company’s operations more streamlined, automated, and scalable.

That was a mouthful, so let me explain a little more.

When I joined the company in mid 2012, our warehouse was run entirely on homegrown iOS apps. It was quite the sight; everyone was walking around doing stuff with iPhones, be it receiving bags, or taking photos and measurements of garments to put on our online store. For our size then, the approach was working incredibly well. But soon, we realized that to achieve scale and higher efficiency, we needed something more robust. Thus, we intensified our focus towards building new systems to improve our operational efficiency.

While doing so, we have not restricted ourselves to any particular platform or language. We knew from the start that to solve such a wide array of problems, we needed a diversified technology stack. The result: our bag receiving is still done using a custom iOS app, our garments are photographed using a .Net station, their images processed using C++ and Python libraries, and the branding and categorization is done using a slick Backbone.js UI with touchscreens (mind you, this is just the inbound side of operations.) That said, our backend is primarily in Ruby on Rails.

Another distinctive feature of Ops Engineering is that  we do not have project managers or business analysts in our team; we ourselves do the managing and analyzing. For me, this makes for a really valuable experience, and I believe it both enhances and complements our teams programming abilities.  On one hand, working with the stakeholders directly to understand business requirements results in better and more suitable features. On the other hand, understanding the technical ins and outs of our systems helps us in explaining the functionality, tradeoffs, and limitations better to the stakeholders.

So what do we do on a daily basis you may ask? I have no straight answer for this. We could be hiding in a room, chugging coffee and coding, or we could be training the ops team on a new feature we just deployed, or we could be analyzing critical metrics from the last quarter and figuring out how we can make further enhancements. We are also not an all-work-and-no-play kind of a team. Some of us go work out together, others go to Meetups and conferences together, and others go tour breweries and discover random bars in SF together.

By the way, we are hiring for a number of engineering positions. If interested, check out our job postings.


Web Engineering at thredUP

by Dan DeMeyere - @dandemeyere

Every company has a different way of organizing and defining their engineering teams. At thredUP, we have three engineering teams. We have a Mobile Team that builds our native iOS/Android apps. We have an Operations Team that focuses on our distribution center's needs (getting our product online, fulfilling orders, handling returns, etc.). Lastly, we have our Web Team.

What is a Web Engineer?

A web engineer is an engineer that focuses on the user-facing, browser-based (desktop + mobile web) thredUP experience. From the moment someone types 'www.thredup.com' into their browser, until the moment they complete their checkout, they're in the web engineer's world. A world that consists of Rails/HAML/SASS/CoffeeScript, improving page load times, and measuring customer engagement metrics.

A web engineer operates differently than engineers on our other teams although we do have an over-arching engineering culture that encompasses all of us. The Web Team works in two week sprints and we have two different backlogs that we work out of. One is our merchandising backlog and the other is our growth & conversions backlog. Each backlog has someone that is responsible for that backlog's roadmap and a sub-team of web engineers responsible for delivering each sprint's projects.

Merchandising is focused on surfacing the best product to our customers as fast as possible. They work on scoring algorithms, improving free text search functionality, collaborative filtering, recommendations, and much more. Their goal is to create a shopping experience uniquely tailored to each customer based on what they have searched for but haven't purchased and what we can recommend to them based on what other customers with similar tastes have purchased.

Growth & conversions is always focused on a specific layer of our funnel. We consider getting new customers to the top of the funnel as the growth layer. Our conversion layers are getting customers to add a filter -> add to cart -> go to checkout -> complete checkout. Getting customers to become brand advocates and invite their friends is an example of something that affects both growth & conversions. All of our funnel's layers have clearly defined KPIs that we try to improve each sprint.

Including myself, there are currently 8 engineers on the Web Team - two are on the merchandising backlog and six are on the conversions backlog. We used to shuffle which engineers comprised each sub-team, but over time engineers gravitated towards the team they cared about the most after they became engrossed with that team's metrics/goals. We feel that if you care about what you're doing, you'll make a bigger impact so for the most part web engineers can decide which backlog they want to work out of.

What does a web engineer do?

Now you have some context to what a web engineer is and how they help the drive the product forward. The layman would assume that web engineers spend all their time cranking out code; however, web engineers are responsible for much more than that.

To take a step back and speak in very general terms, companies exist to serve the needs of the public and generate profits for the shareholders. For companies to exist for an extended period of time, they need to become profitable (there are obviously some exceptions here). Companies that are not profitable should be doing everything in the power to become profitable. At an eccomerce company, it takes time, research, and proper execution to close the gap to become profitable. Our executive, product, and marketing teams are tasked with providing the vision on how we're going to close that gap. The Web Team's role is to fulfill the needs of these teams so we can make their vision a reality.

In the ideal world, the more time web engineers spend doing development the faster we can become profitable. My responsibility is to work with the Web Team and put processes into place that maximize development time in a sustainable way. If the processes are not sustainable, engineers will burn-out, technical debt will be accrued, bugs will overwhelm the user experience, and the team will fall apart.

The processes we have put into place determine the composition of how a web engineer allocates their time. Here is a simplified list of responsibilities for web engineers:

  • Complete the development stories in each sprint.
  • Only push code that improves the overall quality of the code base.
  • Thoroughly review your peer's pull requests to reduce the number of bugs that are introduced into production.
  • Squash bugs as they come in or create a story with enough details so another engineer can squash it.
  • Handle escalated customer services tickets to be exposed to the problems our customers are encountering.
  • Use the product so that all development can be done within the context of the customer's needs.
  • Define and work towards professional development goals.
  • Mentor and/or teach other engineers to increase the technical competence of the team, transfer knowledge, and help your peers work towards their professional development goals.
  • Attend our engineering book club to further our growth as engineers.
  • Help evolve our engineering team culture.

It's a challenge to do all of these well, but no one said that engineering was an easy profession. At thredUP, we pride ourselves in hiring engineers that care about our product, our code, our processes, and each other as much we do. If you would like to join our team, we have two open positions:

Service-Oriented Rails Engineer

by Dan DeMeyere - @dandemeyere

thredUP's engineering team has reached the point where we're focusing on breaking apart our tightly coupled systems and moving them into service-oriented systems that can scale. It's a challenging and fun stage in our team's evolution and we're looking for the right engineer to help us make this happen.

We're looking for someone who has experience building SOA systems or at the very least has worked on a team that already has their services scaled out. We're looking for someone who becomes excited about separating responsibilities and likes to talk about the merits of different messaging patterns. We know you're out there.

Hiring is a two-way road. We need to be a fit for you too so let me tell you about our team. We care a lot about engineering team culture. The engineering team meets every two weeks to discuss and iterate on it. We have an engineering book club. We've been known to geek out on board games. We care about mentoring, professional development, code quality (yes we use CodeClimate), thorough testing, and reviewing code in a way that informs and educates the team to make us all better engineers. These are qualities our team is passionate about. If you're passionate about these too and you have the experience we're looking for, we'd love to hear from you.

More About Our Team

  • 2 Rails teams (Warehouse Operations & Web) comprised of 12 engineers. 1 Mobile team with 2 engineers (1 iOS, 1 Android).
  • Code reviews are done through pull requests on GitHub.
  • We primarily use MySQL, but also use Redis/Memcache/NoSQL when applicable.
  • AWS for our server needs.
  • Jenkins for our CI server (RSpec/Jasmine tests).
  • We use Campfire to communicate and post funny Gifs during the day.

Desired Skills & Experience

  • 2+ years of Rails experience either architecting or working within service-oriented architecture.
  • Believer in testing.
  • Experience with message queueing (ex: RabbitMQ). Preferred, not required.
  • Bachelors or above in Computer Science.

Compensation & Perks

  • Competitive salary and equity.
  • Work from home Wednesdays.
  • Health, dental, and vision insurance.
  • Apple LED Cinema display + computer of your choosing.
  • Stocked fridge + snack cabinets.
  • Office is located at 2nd & Market in downtown San Francisco (right next to Montgomery BART station).

Integrating your rails app with Dropbox

By Chris Homer - @chrishomer

At thredUP, we recently started using dropbox to do more than just store and share files among employees.  We've now integrated it with a couple of our applications so that certain data sets get archived there.  We used to just send them by email if they were small enough or save them to a server and then download them manually.  Now, with dropbox, they get dropped in a shared folder and the people that need access, have it.  

Implementing this integration had a couple hiccups along the way and I want to share how we did it in this post.

First, we used the dropbox-sdk gem (https://www.dropbox.com/developers/core/sdks/ruby) to handle most of the heavy lifting but you still need to implement a workflow to gain authorization with dropbox.  

We wanted to be able to authorize a conneection and persist the session to the database so we could restore it and work with dropbox without having to reauthorize again.  To accomplish this, we wrote a model for storing a users authorization session information:

As you can see, it's a fairly compact class. Here's how to use it:

With this wrapper class it's really that simple.  You could always implement a simple scaffold for this class and customize it to handle the auth workflow through the web browser - we don't add accounts that often, so didn't take this extra step.

A few more client use tips:

Hope this helps you integrate with Dropbox in your own applications!

Reviewing MailChimp's Transactional Email Service: Mandrill

by Dan DeMeyere - @dandemeyere

As soon as your website amasses a sizable amount of users - probably somewhere around 50,000 or so - you're going to require two different types of emailing services. One for mass email (emails sent to your entire user base) and one for transaction email (emails sent to individual users after an action such as placing an order).

Mass Emailing Service

The reason you need a separate service for mass emailing is because sending emails is both CPU-intensive and time consuming for your servers. The thredUP dev team made the switch to a 3rd-party service after we tried using our servers for sending out a promotional email to our first 100k users. The email took about 4-5 hours to complete and we even spun up extra Amazon EC2 instances to help fire the emails off. Considering the email was a 24-hour site-wide promotion, it created an awkward user experience as some users had more time to use the promotion than others. Additionally, when people started talking about the promotion on Facebook, some users started to write in wondering why they didn't receive the promotion. We knew at that point we had to switch to a service that scaled better than our own so we made the switch to MailChimp.

Services such as MailChimp or ConstantContact are built to send out hundreds of thousands of emails in a matter of minutes, which is exactly what we needed. I had used ConstantContact at a previous job and while it got the job done, it was expensive and outdated. For an example, if you go to ConstantContact's developer docs, here are the library wrappers they offer: ColdFusion, PHP, and C#. So if you built your website 10 years ago, their libraries are probably relevant (sorry PHP).

When you compare this to MailChimp, which has an entire mini-site dedicated to their API documentation , the decision for who to choose should be obvious. As it currently stands, the thredUP Rails app is integrated with MailChimp to add/remove users to our mailing list based on the email preferences they have chosen. If we send email through MailChimp or manually through our app, the user's email preference stay synced. This is just one of the many ways thredUP has integrated with MailChimp through their API.

Transactional Emailing Service

Similar to mass emailing, you can get away with sending transactional emails on your own for a while (just make sure you're doing background queuing as the sending of an email should never be reflected in a user's page response time). Since these emails are sent on the fly (i.e. moments after a user has placed an order) the hardware requirements are much less than mass emailing as the computational load of transactional emails is spread out across the day.

The reason you make the switch to a service that handles ad hoc emailing isn't because of a lack of hardware infrastructure (at least initially), it's because there are other factors at play once you're sending out thousands of emails a day to different domains (Gmail, Yahoo Mail, Hotmail, etc.). You have to start worrying about ISP monitoring, IP white/black labeling, and SPAM reports. These issues can allow an email provider like Hotmail to throttle or completely stop your website's emails from going through to the user's email inbox, which creates a lot of user experience problems (i.e. try resetting your password at any website without receiving email).

What if you're a data-driven company? Are you going to build an in-house email analytics suite? I'd hope not. For the reasons I mentioned and many more, it's better to pay someone better at delivering transactional email than you are. Initially, we made the switch to SendGrid. SendGrid was great to us. Good pricing, good metrics, good API, and much more. We used SendGrid for over a year, but it was lacking one component we desperately needed for our marketing team - online email editing.

Given that thredUP is a data-driven company, it shouldn't be a surprise that we run a lot of A/B tests. Testing different email subject lines, call-to-action buttons, and headers are all very easy to change....for developers. Developers quickly became a bottleneck for the marketing team to roll out changes/updates to emails. Even if there was just a typo that needed to be changed, someone from the marketing team would have to ask a developer to make the change in the code and deploy the changes before the typo was fixed. That process wasn't fast enough and no developer wants to be updating emails all day so we started looking for an email service that was transactional and provided an online interface for editing email templates. Enter Mandrill.

Mandrill

Mandrill is MailChimp's new transactional email service. It's awesome.

I'm a big fan of Mandrill for a number of reasons. First, let's start with their online email editor. Through their interface, you can view all the emails you have put in their system, edit/delete/publish any email, and add new ones at will. This allows non-developers to go in and make text changes and if they have HTML experience, they can edit the entire email.

If you're wondering about dynamic information in an email (user's name, order totals, etc.), don't worry as they've thought about that as well. When your app sends the API request to Mandrill, you pass in the dynamic data and they inject that information into the email for you. Suggestion for the Mandrill team: it would be nice if there was some sort of templating partial system. We have shared layouts for a bunch of our emails and when we want to change the design, we're forced to update every email for that layout.

Next up is their customer support - so far it's been stellar. This past Saturday I noticed a number of our system emails weren't going out and from our Mandrill dashboard I could tell it was because we exceeded our hourly quota. We made the mistake of queuing up an email to 80k of our users using their transactional system and since we're still new to Mandrill, that exceeded our hourly quota, which they have in place to ensure no one abuses their system. I contacted their customer support team to see if there was something they could do to make a one-time exception. Within 15 minutes they had already responded and temporarily removed our hourly limit to flush out our queue. It's re-assuring to know that in the event something goes wrong, their technical support team is accessible and able to take action.

If you have used or visited MailChimp, you know that their team prides themselves in building a well-designed product and Mandrill's design lives up to their high design standards. The Mandrill dashboard is fantastic. You're welcomed by a large chart of the metrics you care about (emails sent, delivered, bounced, rejected, opened, clicked-through etc.) as well as stats about how many emails you've sent this hour, what your quota is, and your app's email reputation. From there you can start drilling down into more detailed views. Here's the kicker, they have their own free iPhone and Android app as well:

I can't speak for the Android version, but iPhone's app design and UI is great. If you're like me, the more remote access you have to the vital stats of your app, the more you feel comfortable getting time away from your computer.

Lastly, their pricing is very affordable. If your website is small, there's a good chance you can integrate with Mandrill for free.

When I noticed they had a free tier, I integrated Mandrill into my website's contact page, which took all of 2 minutes to configure. I plan on doing a follow-up post on how to install Mandrill for your Rails app as well as talk about some of things their API has to offer.

If you have any thoughts about Mandrill, please comment below!

Dear Experienced Ruby Dev, Come Join Our Team

by Dan DeMeyere - @dandemeyere

First thing's first, I'm not a recruiter. You won't see the following terms in this post: 'hacker', 'rock-star', 'pirate', 'guru', or 'ninja'. I'm not trying to get referral money for getting someone hired. I have no ulterior motives other than trying to find someone who has solid Ruby experience that can join our team, tell us what we're doing wrong, teach us to write code that can scale, and be a part of a team that we have worked hard to build.

Now that the disclosure is out of the way, let me introduce myself. My name is Dan DeMeyere and I'm a developer at thredUP. We have 3 development teams: web, ops, and mobile with 4, 3, and 2 developers on each team respectively. I'm currently the lead for the web team and while I have a solid and practical understanding of Ruby (our website is a Rails app), I'm no expert. I want to learn and so does the rest of the team. Some people say they want to learn, but we mean it. We do 'lunch & learns' on a regular basis to teach each other about new technologies we come across, interesting solutions we implemented, and new libraries/classes we've written, but we're still lacking that go-to Ruby developer who can push us to the next level technically.

While this post might seem like a plea, it's not written out of desperation - we just care a lot about our team and what we're trying to accomplish. We're not slouches, either. Our team is hard-working and highly productive. We roll out features every week and we make sure not to accrue technical debt along the way. We have RSpec and Cucumber test suites and a CI server to run them.

Our Technology Stack

While we're not locked into anything in particular, here is what we're currently working with:

  • Rails 3.1 (soon to be upgraded to 3.2 on Ruby 1.9.3)
  • HAML/SASS/CoffeeScript for our views
  • MySQL (and a couple MongoDB/Mongoid models)
  • EC2, RDS, and S3 for our server and hosting needs
  • Capistrano for deployment
  • GitHub for repository management
  • Asana for project management

If you're curious what else we use and work with, I'm happy to expand via email.

Working at thredUP

Working at thredUP is great. My favorite question to answer when I'm interviewing someone is 'why do you like working at thredUP?'. I have a field day with that question because I genuinely love working at thredUP. thredUP is a meritocracy. Your contributions to the team and company trump everything. Better yet, upper management cares and they pay attention to everyone. If you're putting in extra work, it will not be lost on them. They're also transparent and accessible. Our CEO shows us the same presentation he shows our board every month. He'll tell you how much money we have in the bank, what our burn rate is, what he's excited about, what he's worried about. There are no closed doors at thredUP, we're all in this together.

Also, thredUP has some great job perks:

  • Work From Home Wednesdays
  • Catered lunches twice a week (plus fully-stocked fridge/pantry)
  • No vacation day limit
  • Big ass Apple LED Cinema display and a computer of your choosing
  • Office at 2nd & Market in downtown San Francisco right next to the BART
  • Competitive compensation

I could go on about why working at thredUP is awesome, but what it comes down to is that you would be joining a close-knit, no-ego dev team that is always looking out for one another. We all tackle bugs and help with Customer Service if a user is experiencing a technical glitch. If something breaks, we don't point fingers at the person who coded it. If you write a piece of the app that experiences a lot of bugs, you're not going to be pigeon-holed into fixing them. No one is stuck 'owning' any piece of the app - we spread the knowledge so the team stays flexible. There are no rogue devs on the team - everyone contributes in a coordinated effort.

We have fun too. Other than the standard company-wide happy hours, we've been known to throw Halo gaming parties, have Scotch-drinking Settler's of Catan nights, and do things like Casino Night. You'll also hear a lot of Arrested Development and Super Trooper quotes being thrown around mixed-in with a cavalcade of sarcasm. Lastly, and what the development team holds very close to our hearts, you'll be exposed to our treasure trove of awesome Gifs that we post during the day in our Campfire chat room.

I'm not listing any ridiculous job requirements that you see in job postings. If you're genuinely interested, have the Ruby experience we need, and are able to work in SF, please email me - dan@thredup.com.