State of Sync, Part 1

Things - Cloud Sync - I Want to Believe

This blog post is about the cloud sync solution we are working on. Finally, some might say. It has been about two years since we first thought about the option to create a cloud sync solution for Things. A lot has happened since then, and we learned many lessons. It was a long and winding road for us, but most of it happened behind closed doors. In the words of one user, our progress has been glacial – and as I sat down to write this post, it was this metaphor that came to mind. Why? Yes, a glacier is slow, but this object – naturally impressive and beautiful – carves its own path, and despite any obstacles, must arrive.

I am not sure whether “impressive” is the most appropriate term for the cloud sync technology we are working on, but it undoubtedly constitutes a most significant feature in all our products – existing or forthcoming. And to us, our cloud sync architecture is certainly beautiful. But why has it taken this long? The quickest way to answer this question is to quote Ken Arnold:

To stop worrying about it will require worrying about it a lot at first.

And that is exactly what we did. With what will be a forthcoming series of blog posts, I will not only look back to give an idea of what it’s like when a software company is worrying – but I will also share some details about the technology that will underpin our solution and what it will mean for our users.

Before getting into those details, it will be useful to explain just what kind of problem a sync solution is trying to solve. Today’s blog post will therefore concentrate on that, but before closing I’ll also offer an overview of where we stand right now.

Perfect Networks

If we lived in a world that had perfect networks, the sync problem would not exist. A perfect network is one that never fails and has unrestricted speeds. Access to remote servers would be instant. With a perfect network, it wouldn’t be necessary to store data on our devices. All our computers and mobile devices could simply connect to a remote server to store and retrieve data. This way all of our devices would have the same data available to them all the time.

But, of course, the network is not perfect. In order to provide a great user experience, it’s still necessary to store data locally on the device. For this reason, all versions of Things come with their own database. Now, in order to make sure the same data is present on each device – no matter where it’s added or changed – the Things databases need to be synced.

Looking for a Common State

What exactly does this mean? Let’s look at an example. A user might have modified her Things database on the iPhone while not being connected to the internet. Back at home she might make changes on the Mac before the iPhone had a chance to send its changes. Now we have a situation where the iPhone and Mac databases have diverged, no longer sharing a common state.

In order to remedy this situation, data has to travel both ways between the devices and undergo a process to make sure that the resulting databases ultimately reach a common state again. This process is called merging. In the example above, assume that the user reordered to-dos in a project on the iPhone and deleted or created to-dos in the very same project on the Mac. During the merge process the devices need to agree on a final state for the project, distribute all necessary data, and make sure the resulting changes are applied correctly.

Conflicts

The merge process gets more complicated in the presence of conflicts. Imagine a user checked off a to-do on one device but deleted it on another. In order to resolve the conflict, a decision has to be made. The deletion can either be ignored or applied; the latter effectively resulting in the completion of the to-do being ignored.

It gets even worse with objects needing to maintain or change their relationships with other objects – like to-dos, projects, areas, and tags; to-dos can be contained in projects; to-dos and projects can be contained in areas; all three of them may have tags. Changing these complex relationships on multiple devices at the same time creates ample opportunity for conflicts. It is the responsibility of the merge algorithm to resolve these conflicts and to make sure all resulting changes are distributed consistently among all devices.

Simply Make It Work?

Providing a sync solution is a complex problem. As might be apparent from what I outlined above, sync bugs have the potential to seriously mess up a user’s data. It is therefore very important to have a solid foundation. But this still does not describe the entire problem. The most difficult part is not to simply make it work, but to create a fast implementation that can scale to millions of users without diminishing the user experience.

Why is a fast sync process so important? When you launch Things, you want your database to be up to date and contain all your to-dos, no matter where you entered them. Since Things cannot update itself in the background due to iOS restrictions, this means that syncing has to take place when the app is launched. A similar situation arises when you enter new todos on your device and quit Things immediately. Add to this the possibility that a network connection might drop at any time. Every conceivable troublesome scenario points to one thing: fast sync is necessary for a good user experience.

Finally, we must consider scalability. Creating a solution for a few thousand users is one thing – creating a solution for millions of users is a different beast entirely. We have all experienced what happens when a web service is accessed by more people than it was designed for; at first, the service becomes slow, then it fails entirely. It has been our primary goal to create an architecture where scalability was not an afterthought, but rather built-in from the beginning.

A True Cloud Sync Solution

This is the first of a series of articles about our cloud sync solution. In the following installments I will talk about the various approaches and technologies we tried while working toward our goal, and why we did not continue with them. I might also touch on a few popular approaches that others have taken, and show why the trade-offs involved were not acceptable to us. I will talk about the lessons we have learned and the final solution which, at last, satisfies all the requirements we feel a true cloud sync solution demands.

Before closing this article, I would like to offer a cursory glance of where we’re at right now: We have created and deployed both server and client-side sync components. Both components are completely general and can be used for any application. They have been successfully tested using a special demo program. We are now in the process of integrating this technology into Things.

The final release of cloud sync as part of Things is still off by a few months. But we plan to publish more details about what we are doing (and have been doing) every few weeks.

Let me end this post by expressing our sincere gratitude for your patience. Driven by ambitions that were almost too high, it has taken us much longer than we expected. On a path lined with unanticipated obstacles and letdowns, it felt at times as if we would never get there – but we kept believing that we would be able to create a fine solution; a foundation for many cool things to come.

It is now in reach.

An Empty Canvas

If it is not just a different “form factor”, if it is not just old software with the “touch experience” added, then what is it? What makes the iPad so special we just had to develop Things for iPad?

For sure, the introduction of the iPad today marks the arrival of a new platform. And there is hardly anything more exciting for a software developer than the introduction of a new platform. But this isn’t just any platform.

If you want to understand what makes the iPad special, you cannot look at what it has, but what it doesn’t have. The iPad is so thin and light, it becomes the display, and the display becomes the application. No input devices. The device vanishes and turns into the application you are using. The technology is transparent.

Blank Canvas

Steve Jobs said about the iPod that “it is all about the music”. With the iPad, Apple has done the same for personal computing as it has done before with the iPod: it made technology go away. But if the device is gone, and the operating system is gone, what is left?

The iPad is an empty canvas that invites us to imagine what is possible. It inspires our imagination and it makes us want to create, because never before were we able to create software that was so close to the user.

Developing Things for iPad in such a short amount of time was exciting, it was hard work, and it was a whole lot of fun. You can see how much fun we had by watching the Things for iPad introduction video. Please enjoy it.

Things 1.3.2 Brings Multiple Mobile Device (including iPad!) Sync

Today we released Things 1.3.2. Despite the version number saying that it is only a minor update, it actually contains a significantly enhanced sync engine.

With Things 1.3.2, it is now possible to sync an arbitrary number of mobile devices with your Mac such as the iPhone, iPod touch, or iPad via your local network. The Devices preference pane (previously called iPhone) will guide you through the necessary steps to add multiple devices.

Multiple Mobile Devices Sync

Once you start a sync session by choosing the "Sync Mobile Devices now…" menu command (or by simply opening Things on one of your mobile devices), Things will look for all available devices and sync all of your information between all of them.

For example, if you made changes on both your iPhone and your iPad, Things 1.3.2 will sync with your iPhone, then your iPad, and once again with your iPhone to make sure changes are not only passed from your iPhone to your iPad, but also back again from your iPad to your iPhone.

Finally, for those of you who are wondering about cloud sync. We have chosen a quite ambitious approach using cool technology that only recently has become feasible. We are (still) very hard at work to get this completed and released, and I want to thank everybody for their patience. It'll be worth the wait.

Things touch 1.4: Landscape and Global Search

Today we released an update to Things for the iPhone and iPod touch that introduces global search and enables landscape support. The latter can be turned off in the settings.

Landscape Mode
Global Search

Due to the space constraints on the iPhone, not all of our screens fit into landscape so we had to be creative. One example is the due date picker. In portrait, it looks like this:

Due Date (Portrait Orientation)

In landscape, however, the date picker is too tall and doesn't fit on the screen together with the two information lines. We solved this problem by moving the picker down one level in the hierarchy - but only in landscape mode:

Due Date (Landscape Orientation)

There are also many bug fixes and improvements in this release, a list of which can be found here. Among them is a significantly faster sync process that compresses the tasks before sending them between the devices. An update for Things Mac that enables this feature is currently getting the finishing touches and will be available shortly. In preparation for the iPad launch, the new Mac version will also gain the ability to sync multiple mobile devices at the same time.

Originally, we planned for the 1.4 release to also include repeating tasks. By now, we have them fully implemented in TT and already sent out a few beta versions to our testers. The main remaining work is ensuring that repeating tasks sync reliably with the Mac. This is quite involved and requires updating and migrating Things Mac to use our new recurrence rule engine. Work on this is still ongoing and we didn't want to hold back all the other improvements of 1.4 until they are completed. This is why we released TT 1.4 without repeating tasks for now. Once they are completed, we will add them in the next major update.

Finally, if you've seen our new "About" page or our most recent blog post, you will have noticed that our team has grown quite a bit over the last year. In addition to the people you see in the caricatures, we also had the pleasure of having two very talented young programmers as interns: Devin Lane and Kent Sutherland. Kent (whom you may know from his iChat add-on Chax) has written large parts of the code from this release and I want to thank him for his excellent work.