Zoro

zoro-screenshot

In June of 2015, I accepted a position there as a Senior Software Developer at Zoro, a sizeable eCommerce company that relies on heavily on software automation. After about a year of establishing myself as a technical leader and mentor to other devs, I was promoted to the position of Solutions Architect where I was able to work with all elements within Zoro’s IT department and have a guiding hand in the company’s technical direction. And after about 18 months in that role, the new director-level position of Chief Architect was created for me and a formal architecture team was established, allowing me to have a hand in shaping not just the technical direction of the department, but to be involved with staffing, budgetary, and organizational concerns as well.

At Zoro, the leadership role that I had organically created for myself in previous positions has been officialized, and as a “senior” developer, I found that I would less time worrying about my own work, and more time worrying about the work of my team. This continued to evolve in my role as Solutions Architect, where I was able to work closely with all of Zoro’s development teams (usually around 3 at any given time) and help each team member take ownership of the projects they were developing and maintaining. And through all my positions at Zoro I’ve worked hard to help create and maintain an open and collaborative engineering culture that I believe has been a major factor in the team’s success.

Some of my major accomplishments in my time at Zoro include:

CircuitBreaker

I created a circuitbreaker library and oversaw its implementation into several of Zoro’s applications. Many pieces of the Zoro architecture rely on API calls to various 3rd party services to function properly. If one of those services were to fail the application was usually able to gracefully degrade, but only after the timeout for the API call had elapsed. This meant that if a 3rd party service went down it could have drastic impact on the performance of the application, which in turn could occupy all available gunicorn workers on the production server and prevent Nginx from proxying requests properly. If one of our 3rd party services went down, it was not uncommon for it to take the entire application with it.

The circuitbreaker resolved this by simply getting the application to track the health of the calls that it’s making. Pass the circuitbreaker a list of services (generally a primary option, a backup for if the primary is down, etc) and it will return the first service in that list which is healthy. Once the call is made, the calling code uses the same circuitbreaker object used to retrieve the healthy service to report on whether the call had been successful or not. A customizable threshold determines if a service has had too many failed calls and marks the service as unhealthy if it does.

In addition, the circuitbreaker can recover unhealthy services automatically. By default the circuitbreaker will test unhealthy endpoints by returning them for use on a small percentage of calls. This way, once the service recovers it will start recording successes and eventually the failure rate will rise above the health threshold, allowing the service to be marked as healthy again.

Zoro Internal Modules

Zoro Internal Modules is a repository built as a PIP distributable package. It was born out of the need to have a centralized place for common operations that are frequently used (and often implemented differently) in various locations of Zoro’s wide ranging codebase. The growing package consists of several modules which each have a specific focus. Some examples are:

  • Zoro Data Access

    This access as an abstraction between a data store and the code that needs to read from said data store. In the same way that an ORM can abstract a connection to a variety of SQL basded databases, the idea with the data access layer was to create an API that could be used to interact with virtually any type of data store by updating the internals. The idea was born during an effort that saw Zoro’s primary store of product data move from a MySQL database into ElasticSearch. With no standard Python implementation of a high-level ElasticSearch API, we were faced with building the raw JSON for ElasticSearch queries in a wide range of applications. To avoid this messyness, I lead the effort to design the data access layer API and create implementations for several data stores in Zoro’s ecosystem.

  • Zoro Business Logic

    A question that has plagued many an architect: where do we put the business logic? By creating this module and giving it a blindingly obvious name, my goal was to have a single obvious location to house all logic shared by more than one application. The advantages of this structure have been twofold: first, it prevents two different applications from inadvertently computing some value differently since they are relying on the same module to perform that computation. Second, it acts as self-documentation of the business decisions that have been made. If a developer ever needs to know how an SEO-friendly URL slug is constructed, they know exactly where to look to find out.

  • Zoro Data Types

    These are simple class wrappers for commonly used data types (like “Product” or “Category”). By wrapping this data in a class instead of just passing a raw dictionary around, I was able to provide easier access to helper methods (often defined in Zoro Business Logic). Additionally, having an interface that looks like

    instead of not only makes the code cleaner and more readable, it means that client code making use of these functions doesn’t need to know anything about how they work or what arguments they take, the data type class takes care of that.