Building Push-Triggered Sync, Part One: Choosing a Language

Here at the Omni Group, we have a long history of writing code in Objective-C. All of the apps we currently sell are written in Objective-C, and those of you that follow our public frameworks will know they’re entirely Objective-C as well.

However, we recently faced a new challenge with our decision to bring Push-Triggered Sync to OmniFocus on Mac and iOS. Apple’s architecture for sending push notifications requires that we use a server-side component called a provider. And while Objective-C was our forte, it was ill-suited for server-side development, since almost none of Omni’s servers run OS X.

Thus, our attention turned to building a provider that could handle the large existing OmniFocus customer base, along with the specific traffic patterns the app generates. (For example, the Omni Sync Server often sees large traffic spikes early Monday mornings, as OmniFocus users get started on their work weeks.) What’s more, we wanted this provider to fit well in our existing server setup, which is gradually moving towards using FreeBSD.

With these constraints in mind, we settled on the Go language for implementing a push provider. Go had several properties that we felt made it a good fit for this feature:

  • It was explicitly targeted at system-level services, rather than our usual focus on apps with rich user interfaces. In particular, Go’s multitasking features (such as first-class functions and goroutines) made it well suited for building a parallelizable server.
  • It has a strong standard library, especially around networking and manipulating arrays of bytes directly — two especially relevant topics for interacting with Apple’s binary notifications interface across the Internet.
  • It is a relatively young language, and so is able to take advantage of recent advancements and best practices in language design. On the flip side, it’s not too young: with Go 1.4, the language has reached a level of maturity sufficient to freeze the API, providing a certain amount of stability in Go projects.
  • It’s a compiled language with FreeBSD as a “first-class” targeted platform, giving us confidence that we could deploy a provider binary across our hosting infrastructure without needing a custom environment or runtime installed up front.

After settling on Go, we also considered various open-source packages for speeding up early development. And while we did wind up using a few (for tasks like MySQL and PostgreSQL database access, as well as logging), existing frameworks for communicating with Apple’s push service (APNs) didn’t quite look as fully-formed as we would’ve liked.

With that, the stage was set: in Go, build an internal framework for communicating with APNs, then use it in a provider daemon that could power push notifications for the hundreds of thousands of customers that rely on OmniFocus every day. We’ll discuss more about specific implementation details next.