Matt Aimonetti shares lessons learnt during his quest to find the right technology to build software at

For more videos, visit our new Videos channel.

Ben Manns, Software Engineer at Doximity spent some time a couple weeks ago giving the team a talk about using Apache Kafka and Samza to automate ingestion of database changes. The use-case of his talk was about leveraging Samza to watch MySQL binary logs and Kafka as the pub-sub messaging system to update our Elasticsearch indexes with the proper updated documents. Checkout the video of the talk below.

For more videos, visit our new Videos channel.

Having a defined workflow has huge advantages. It adds discipline and structure to a process, helps focus on one task at the time, and a whole lot more. Here at Doximity, the mobile team has honed one of its workflows by applying a general convention for branching and pull requests on Github. This convention is great because it leads to structured and manageable repositories. But, as you’ll see below, it can be a bit labor intensive.

Let’s start with a look at a branch graph of a repository. It usually looks like this in its most basic form:

In this process, the changes for each feature are code reviewed on their own pull request to the version branch. And each merge to the Master marks a new release.

It looks simple, but just imagine what you need to do in order to create a pull request for a simple one-line fix on the code.

$ git checkout -b new_branch_name
$ git add -A
$ git commit -m "commit message"
$ git push --set-upstream origin new_branch_name

After all that, you’d open up and create a pull request from the site. At Doximity, we also link the created pull request with its corresponding story on Pivotal Tracker by putting the story link in the PR, and vice versa.

To me this is way too much work for committing a single line change. It’s also really redundant for major changes. Thankfully, there’s a tool to help.

Introducing PRH (Pull Request Helper)

Pull Request Helper (prh) is a simple python command line interface (CLI) application. It uses subprocess in python and an API from hub to do all that work above with a simple and easy command. The equivalent of the above process with prh is:

$ prh -b new_branch_name

That’s all there is to it! In the process, prh:

  • created a new branch called new_branch_name
  • committed all the changes (with the default commit message)
  • pushed the commits to origin
  • created a pull request using hub API (with the title of "new branch name")
  • opened the pull request in a browser

But wait. What about linking the story to the PR? For that, all you need to do is use -m option and add a link to your story, like this:

$ prh -b new_branch_name -m https://your/pivotaltracker/story/link

You can see the results on Pivotal Tracker as a comment on the story:

You can also see it on your PR as the pull request body:

The case above is only one of many supported by prh. You can also use it to create a PR when you’re already in a feature branch (using -upto option) or even commit your code in a new branch and create its PR to another branch (using both -b and -upto together).

There are many more options for customization. These include -pb for adding a message to the pull request body and -pt for changing the default pull request title. Or, if you wish to add just one of the changed files, you can use -a option with the file’s path.

No matter how you customize, automating the committing process using prh will save time and prevent mistakes.

To read about all the customization options and download prh visit PullRequestHelper.

Looking Forward

We wrote prh with extensibility in mind. That means it won’t take much for you to fork the repository and make it match your existing workflow with some simple modifications.

Pull Request Helper is an open source project. You can contribute by adding and improving the code, requesting features, or reporting bugs. And don’t forget to check out the requested features at the issues page of the project. Thanks and enjoy prh!


python 2.7

Get started using PRH

Learn more about Vital
Get started using Vital
Integration with Rails: Ruby Gem

Another Front-End Framework... Why?

With an abundance of well-known options that are backed by years of refinement, why reinvent the wheel?

The answer is simple: The wheel doesn't fit.

The Problem

The allure of quick setup drew us into experimenting with Bootstrap in some applications. Setup was easy, but maintenance was not. We spent more development effort that we would have liked to tackle simple problems.

Customizations to meet business requirements became difficult. Since there was already so much code and structure in the original framework, customization always resulted in excess amounts of code. This made for an unpleasant and unmanageable code base. There were also too many framework options and features that went unused.

While we could have customized the build to decrease the size of the footprint, the complexity and size of individual components was still too great. Massive frameworks like Bootstrap and Foundation were just too bloated for us.

Get Real

The issue became real several years ago when our early stage startup went from having to maintain one application to about ten. We needed a custom solution that could scale as fast as we did. So we decided to continually develop and maintain our in-house framework.


Productivity was a key factor in the formalization of Vital. As the need for a multitude of small applications grew, so did our users demand for mobility. The framework needed to encapsulate easy mobile optimizations while still maintaining desktop friendliness.

Some things we wanted out of Vital:

  • Light enough to load and render quickly on slow cellular networks
  • Scalable on all devices and screens
  • Easy to read, write, and maintain
  • Quick to compile and refresh locally
  • Customization friendly
  • Doesn’t require heavy nesting, structures, or classes


Everyone writes code a little differently, and that’s okay. But when working in a team, code should be somewhat consistent. We wanted to allow code style to be flexible enough for individuality in code, but rigid enough to minimize technical oversight. This allows new and existing team members to work efficiently.


Our mobile usage exceeds our desktop usage, so we wanted to keep Vital lightweight and optimized. We integrated the ability for each application to generate custom font iconography, keeping HTTP requests to a minimum. In addition to being quick, most form elements render consistently while gracefully degrading on legacy browsers - a huge plus for branding.

At just 22 KB minified, the Vital CSS framework is very small. Vital is also written almost entirely in em values, so scaling is easy and the code remains minimal.

Size Breakdown:

Size Gzipped
CSS Framework 22 KB 6 KB
Icons (.svg) 3 KB 1 KB
Icons (.eot) 2 KB
Icons (.ttf) 2 KB
Icons (.woff) 2 KB
Javascripts 0
Total 31 KB

Did We Make The Right Choice?

Simply, yes. When our business requirements change, we pivot faster than ever. Writing and editing has never been easier. Maintenance across various applications has been minimal. Vital is currently integrated into all of our applications that have a UI. Each application is fully customized to meet user and business needs.

Learn more about Vital
Get started using Vital
Integration with Rails: Ruby Gem

Although headquartered in San Francisco, Doximity has a thriving remote work culture. While the office is the historical hub of activity, a large portion of our hiring over the last several months has been remote workers. Remote employees might take a back seat to on-site workers in a lot of offices, but, at Doximity, remote workers are first-class citizens.

Meetings and Communication

We strive to stay as lean and agile as possible and to create a culture that isn’t overly focused on meetings. That doesn’t mean we’re opposed to them — in fact it’s quite the opposite. Person-to-person communication is important and fosters a sense of connection and team building. To put that into a real-world perspective, you’re not going to have meetings all day, and the ones you do have are quick, focused, and important. As a company, we’ve invested in the infrastructure to make these more seamless and plan to keep that up as we grow.

A little bit about company structure: there are several different main teams, each working on a different product. For example, on the DocNews team, we begin the day with a standup meeting. Each participant is expected to talk about what was done the day before, what they'll be working on that day, and any blockers they may have encountered. It’s a good way to stay in contact with the team and, in addition to the intrinsic value of the standup, makes remote employees feel connected. Not every team does stand-ups but the infrastructure and options are there.

“Estimation meetings” are used to gauge how many points to assign to different stories. We talk about the feature and all give a thumbs up when we’re ready to estimate. Estimating points is done in a rock-paper-scissors-esque manner where we count to three and then put up fingers corresponding to the number of points we think a story should take. If we have different opinions on point assignments, we take time justify our position.

We recently started using a web app called Stickies for our retrospectives. This lets remotes participate just like they were in the room. We also use live video chat during the meeting and collaborate using the app and Slack. Read more about retrospectives at Doximity to get more insight into how they work for us.

Pair programming is also something we remoters do occasionally. This is generally up to the people who want to pair; we don’t force mandatory pairing time. Schedules permitting, coworkers are almost always up for pairing. We’ve mostly used Skype for this, but we also occasionally use tmux and a shared connection.

Hardware and Software

We use the typical tools to manage communication across our team:


We use Slack for pretty much everything. In-office text communication is done with Slack, which puts remote workers on the same playing field as everyone else. All of our deploys are done via in-house software which is controlled via bot. This lets any engineer have visibility into what's happening at all times. Most teams have their own channels (or several) where pertinent data is accessible, and the same applies to shared roles such as QA.

Everything Else

We make use of Google Hangouts, Skype and appear for video chats and screen sharing. Now that Slack is testing out video and audio chats, we may start using that more actively. Skype is slowly being phased out but we do have employees who prefer it.

Occasionally, we’ll use a remote tmux session for pairing. When that isn’t feasible, we use Screenhero. Our timezone account gives us a nice view of current times for remoters.


Some of our conference rooms have recently been outfitted with Chromeboxes, which have exceptional video and audio quality. These help tremendously and have the least amount of headaches when setting up.

In Person Visits

Even though working remote has tons of benefits, so does face-to-face interaction. Remote workers can visit the office every couple of months between our off-sites. We have two corporate lofts very close to the office where employees can stay.

New employees come to the office for their first week. This time functions as an introduction to the office, team, products, and the process. Developers are expected to make a commit and production deploy on their first day. There is also a series of presentations that teach about the company, culture, and introduce new hires to their coworkers.

Working in the office also means you can hang out at the J-Bar, an office staple. As the name suggests, there is alcohol available should you wish to partake, as well as a gorgeous view of San Francisco. It’s also where we do our lunch and learns, meet-ups, and larger meetings. There is a camera and mic setup where remote participants can see and hear what’s going on as well as ask questions and interact with the presenter.

We also have off-sites every quarter. The off-site locations are different each quarter so we get to experience new places. With a diverse and remote team, off-sites are a chance to get everyone together in person. This helps to maintain the culture and provide an opportunity for everyone to realign and prioritize goals. We also share what we’ve learned and worked on the previous quarter and squash outstanding bugs in our bug bash.

A full development retrospective is done at each off-site. We try and concentrate on larger issues affecting all teams. I’m not trying to imply it’s all smooth sailing — it took a while to have a consensus on whether 80 or 120 characters is the proper line length for a Ruby file. (It’s 80, in case you were wondering.)

We’re Hiring

If you like what you hear about our remote environment, drop us a line and follow us on twitter. We’re hiring, and, obviously, remote workers are welcome :)

Special thanks to Bruno Miranda, Ben Fischer, Jaymes Waters, Greg Lombardo, and Daniel Zajic, and all Dox remoters for their feedback with this article.