engineering@contactually

Engineering Great Design Process

Contactually is a company all about people and relationships. We love our customers — and hope they love us too! For this reason and many others, strong usability and user experience design are critically important to the success of our business. I recently joined Contactually to lead the user experience (UX) team, after having held similar roles in companies such as AddThis, Oracle, and America Online. In this blog post I’ll share some strategies that our designers, product managers, and developers use to successfully collaborate and build great experiences together. Establish Design Standards Frontify Design resources such as style guidelines, design pattern libraries, and corresponding front-end component libraries aren’t just about consistency. These tools work together to help teams design, build, and iterate faster. At Contactually we make style guidelines and brand assets available to the larger organization using Frontify, and are in the process of converting the Contactually web application to React, using Semantic UI and Storybook, a UI component development environment for React. React is a component-based Javascript library for building interfaces, and will allow us to reuse interface components across the Contactually platform. Tools such as these help us create more consistent, customer-friendly experiences more quickly — a big win for a small team. Storybook interface for React Components Balance Building, Iterating, and Fixing Product design and development roadmaps always require trade-offs. There are new features to be explored, existing features to test and iterate, customer questions and concerns to address, and bugs to fix. As an agile design and development team, we plan sprints by distributing a percentage of “points” — which correspond to available developer time — to each of those priorities. We collaborate closely with...

Postgres at Scale: Query Performance and Autovacuuming for Large Tables

Photo by Yu-chuan Hsu There are few large, hard to solve problems that keep your typical software engineer up at night — and a malfunctioning database is absolutely one of them. We’ll walk you through how our team at Contactually discovered the issue of query performance slippage on some of our largest tables (200 mil — 3 billion+ records) and what we did to address it. The Problem: Systematic Degraded Query Performance In early 2016, we noticed query performance on our largest tables were starting to slip in NewRelic. Over the course of a few weeks, queries that were once taking 10ms were now taking upwards of 6 seconds or more. The team considered numerous causes from poorly written queries to expensive background jobs that may be causing systematic performance issues. Eventually, with the aid of NewRelic, Amazon RDS logs, and hundreds of EXPLAIN queries, we came to the conclusion that this was a database level issue, not poorly written queries in our application (a very common cause of poor database performance). The Culprit: Default Autovacuum Settings After days of research, we narrowed in on the cause: the default autovacuum settings for large tables. Photo by Clem Onojeghuo The default settings can cause weeks to elapse without triggering an autovacuuming process to run on a large table. When autovacuuming doesn’t occur, the query planner is using outdated, incorrect data to decide how to most efficiently execute a query. Imagine trying to tell a friend where the milk is in a grocery store using directions from what the store looked like 5 years ago — you’re friend is going to waste a lot of time using your outdated directions. Critical...

Empowering Developers with Consistent, Safe, and Simple Deploy Scripts

Deploying software is a notoriously risky portion of the software development lifecycle. Our industry is littered with stories of ill-conceived deployments that caused huge headaches to deal with and correct. As developers who enjoy the creative output of programming, it’s easy to neglect the operational details of deployments despite the fact that it’s widely believed that simple deployment processes make for happier developers. At Contactually, investing even a small amount of time to develop fairly simple deployment scripts has paid off huge dividends. Let’s look at what we wanted to accomplish with our deploy scripts, how our scripts do this, and what benefits this has provided our development team with. The Goal of our Deployment Scripts We want to have deployment scripts for all major components of our application/infrastructure. In our case: A ReactJS frontend hosted on Amazon S3 A Ruby on Rails backend deployed on Heroku We want to handle deployments of our components to all possible environments. In our case: Staging Production We want to use minimal setup on behalf of the developer, and use existing credentials and permissions to perform deployment actions. What our Deployment Scripts Do We have one deploy script for each of our main repos: our Rails backend and our React frontend. These two scripts have minor variations, but roughly execute the same steps. Some of the steps executed by the scripts are contained in their own bash scripts or rake files. Pre-deployment CLI checks & confirmations First, our scripts run through a series of automatic checks, or forced developer confirmations to help prevent against ill-advised deployments. Confirm which branch you are deploying to which environment Confirm continuous integration specs are passing...

Upgrading a Production Postgres RDS Instance with Minimal Downtime

Photo by Luca Bravo Scaling a web application requires numerous database upgrades, each potentially requiring downtime. I’m going to tell you a story about Contactually, and the lessons we’ve learned during a few of these upgrades. Before upgrading — practice, practice, practice. Early last year, we switched from Unicorn to Puma, a multi-threaded web server. During our initial rollout, we were seeing intermittent spikes in Request Queueing. During root cause analysis, we zeroed in on spikes in Postgres Queue Depth, which is where read and write queries are queued until Postgres is able to complete them and return a response to the client. Additionally, we wanted to upgrade our RDS instances from Postgres 9.4 to 9.5 to take advantage of new features and improvements. Analyzing the Root Cause When the spike in the Postgres Queue Depth occurs, it ties up Puma threads which are waiting for their answer from the database. When enough of these occur, all threads on all servers are stuck waiting from an under-performing database. This means there are no threads available to handle new HTTP requests that are coming in. These new HTTP requests that can’t be worked on sit in the Puma request queue for so long that they timeout before any of the threads are able to address them. It’s worth mentioning that scaling up the number of web servers would only exacerbate the problem because it would increase the load on an already under-performing database. Additionally, these Postgres Queue Depth spikes cause background jobs to take much longer than ordinary. In some cases, these jobs can timeout depending on application specific logic. The Solution — Increase IOPS Photo by Marcus Spiske The number...
Building Contactually’s iOS App 3.0

Building Contactually’s iOS App 3.0

A few months ago, our team decided to revisit our mobile experience, and to evaluate alternative means of developing the next version. In the end, we decided to build our app in RubyMotion! We did this for a variety of reasons, but they largely boiled down to familiarity with the language and available libraries (both Ruby and Cocoapods). After a few months of busily writing code, we thought we’d take some time to talk about how that decision worked out. To start out: we’ve shipped iOS v3.0! It’s in the App Store, and if you haven’t already grabbed it, go do that now, it should provide some context to the rest of this article. Technical highlights of the new app: Customized table views with “cards” Gestures tied to swipe movements on the cards Progressively-loaded lists Detail views with nested tables 400% faster than the previous version (2.4) iPad-friendly through constraints How We Approached Development Building an iOS app on a “blank slate” was both a blessing and a curse. We had no technical debts from a previous API or architecture holding us back, but we were also starting from nothing and needed to build it all back up again. We started with the API (v2 will be published soon!), and took an outside-in approach to its development. From there, we built out a Ruby client that allowed us to interact with the API as though it were our persistence layer (database). With the foundation of these models, we were able to concentrate on the views and interactions. Everything else was table stakes. Everyone expects an app to be able...
Picking a Mobile App Framework

Picking a Mobile App Framework

Note: This is part two in a series.  Part one is here. There’s no shortage of ways to build a mobile app these days. HTML5 is on the upswing (again), and quasi-native frameworks are popping up almost as often as Javascript libraries. Here at Contactually, we wanted to take the time to re-evaluate all of the current leaders in the mobile app framework space to give us the most bang for our buck. We were looking for the framework that gave us: Longevity – we don’t want to have to write from scratch again Interoperability – we have a dev team of very talented Ruby and web developers that we’d like to use across teams if possible. This also ensures that the mobile devs would be able to troubleshoot anything that goes wrong with our API Hirability – we want to make sure that we don’t pick a language that’s too specialized, which would make it hard to make any experienced hires (or experienced hires prohibitively expensive) Developer Happiness – writing for mobile shouldn’t be a burden; we want to pick a language and framework that makes the most sense to the most developers In this search we looked at several mobile app frameworks, but ended up prototyping with three frameworks based on our initial research: Swift 2.0 – The truly native choice. It’s the only one that we looked at that’s sponsored (and actively promoted) by Apple ReactNative 0.12.0 – Facebook’s newly-published framework that brings React to the native environment, complete with bindings RubyMotion 4.4 – Commercial product that allows you to write in Ruby and compile down to App/Play Store...