Skip to content

Commit e7dea7e

Browse files
timsneathvojtarylko
authored andcommitted
Full copy edit
1 parent 595a73c commit e7dea7e

File tree

2 files changed

+55
-56
lines changed

2 files changed

+55
-56
lines changed

Gemfile.lock

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,34 +12,34 @@ GEM
1212
eventmachine (>= 0.12.9)
1313
http_parser.rb (~> 0)
1414
eventmachine (1.2.7)
15-
ffi (1.17.0)
16-
ffi (1.17.0-aarch64-linux-gnu)
17-
ffi (1.17.0-aarch64-linux-musl)
18-
ffi (1.17.0-arm-linux-gnu)
19-
ffi (1.17.0-arm-linux-musl)
20-
ffi (1.17.0-arm64-darwin)
21-
ffi (1.17.0-x86-linux-gnu)
22-
ffi (1.17.0-x86-linux-musl)
23-
ffi (1.17.0-x86_64-darwin)
24-
ffi (1.17.0-x86_64-linux-gnu)
25-
ffi (1.17.0-x86_64-linux-musl)
15+
ffi (1.17.1)
16+
ffi (1.17.1-aarch64-linux-gnu)
17+
ffi (1.17.1-aarch64-linux-musl)
18+
ffi (1.17.1-arm-linux-gnu)
19+
ffi (1.17.1-arm-linux-musl)
20+
ffi (1.17.1-arm64-darwin)
21+
ffi (1.17.1-x86-linux-gnu)
22+
ffi (1.17.1-x86-linux-musl)
23+
ffi (1.17.1-x86_64-darwin)
24+
ffi (1.17.1-x86_64-linux-gnu)
25+
ffi (1.17.1-x86_64-linux-musl)
2626
forwardable-extended (2.6.0)
27-
google-protobuf (4.28.3)
27+
google-protobuf (4.29.3)
2828
bigdecimal
2929
rake (>= 13)
30-
google-protobuf (4.28.3-aarch64-linux)
30+
google-protobuf (4.29.3-aarch64-linux)
3131
bigdecimal
3232
rake (>= 13)
33-
google-protobuf (4.28.3-arm64-darwin)
33+
google-protobuf (4.29.3-arm64-darwin)
3434
bigdecimal
3535
rake (>= 13)
36-
google-protobuf (4.28.3-x86-linux)
36+
google-protobuf (4.29.3-x86-linux)
3737
bigdecimal
3838
rake (>= 13)
39-
google-protobuf (4.28.3-x86_64-darwin)
39+
google-protobuf (4.29.3-x86_64-darwin)
4040
bigdecimal
4141
rake (>= 13)
42-
google-protobuf (4.28.3-x86_64-linux)
42+
google-protobuf (4.29.3-x86_64-linux)
4343
bigdecimal
4444
rake (>= 13)
4545
http_parser.rb (0.8.0)
Lines changed: 38 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
11
---
22
layout: post
33
published: true
4-
date: 2024-12-01 10:00:00
5-
title: How Swift on Server powers Things Cloud
4+
date: 2025-02-21 10:00:00
5+
title: How Swift's Server Support powers Things Cloud
66
author: [vrylko, wjainek]
77
---
88

9-
At Cultured Code, we’ve recently completed a major transition: our Things Cloud service now runs entirely on Swift. After a year in production, Swift on Server has proven to be reliable, performant, and remarkably well-suited to our needs.
10-
11-
*Note: This article is an adaptation of [our recent talk](https://youtu.be/oJArLZIQF8w?si=hLr6g5MmYH3-5K1c) at the Server-Side Swift Conference.*
9+
You might be familiar with [Things](https://culturedcode.com/things/), a powerful personal task manager that has won multiple Apple Design Awards and is available across Apple devices including iPhone, iPad, Mac, Apple Watch, and Apple Vision Pro. At Cultured Code, the team behind Things, we care about a great user experience across every aspect of the product. This extends to our server back end, and after a rewrite our Things Cloud service has transitioned entirely to Swift. Over the past year in production, Swift has consistently proven to be reliable, performant, and remarkably well-suited for our server-side need.
1210

1311
<img
1412
alt="Things logo"
@@ -17,9 +15,7 @@ At Cultured Code, we’ve recently completed a major transition: our Things Clou
1715
style="max-width: 80%; width: 160px; height: auto; margin: 0 auto; display: block;"
1816
/>
1917

20-
[Things](https://culturedcode.com/things/) is our delightful personal task manager, available on all Apple platforms, with two Apple Design Awards to its name. At Cultured Code, we deeply care about a great user experience in every part of the product.
21-
22-
This commitment extends to our backend. [Things Cloud](https://culturedcode.com/things/cloud/) silently synchronizes to-dos across devices, serving as the backbone of the app’s seamless experience. The system’s correctness is ensured by a rigorous theoretical foundation, which is inspired by operational transformations and Git’s internals. After twelve years in production, Things Cloud has proven to be reliable and robust, and has earned our users’ trust. Yet, even as the conceptual foundations held strong, the technology stack fell behind.
18+
[Things Cloud](https://culturedcode.com/things/cloud/) serves as the backbone of the app’s experience, silently synchronizing to-dos across devices. The robustness of this work is ensured by a rigorous theoretical foundation, inspired by operational transformations and Git’s internals. After twelve years in production, Things Cloud has earned our users’ trust in its reliability. But despite the enduring strength of the architecture itself, the technology stack lagged behind.
2319

2420
<div style="margin: 2em auto;">
2521
<img
@@ -28,87 +24,90 @@ This commitment extends to our backend. [Things Cloud](https://culturedcode.com/
2824
width="840" height="473"
2925
style="max-width: 100%; width: 100%; height: auto; margin: 0 auto; display: block;"
3026
/>
31-
<div style="text-align: center; font-style: italic; margin-top: 1em;">Things Cloud synchronizes to-dos across different devices.</div>
27+
<div style="text-align: center; font-size: smaller; margin-top: 1em;">Things Cloud synchronizes to-dos across different devices.</div>
3228
</div>
3329

30+
## Switching to Swift
3431

35-
## Why we switched to Swift
36-
37-
Our legacy Things Cloud was built on Python 2 and Google App Engine. While stable, the backend suffered from a growing list of limitations. Slow response times impacted the user experience, high memory usage drove up infrastructure costs, and Python’s lack of static typing made every change risky. For our push notification system to be fast, we even had to develop a custom C-based service. As these issues accumulated and several deprecations loomed, we decided to take action.
32+
Our legacy Things Cloud service was built on Python 2 and Google App Engine. While it was stable, it suffered from a growing list of limitations. In particular, slow response times impacted the user experience, high memory usage drove up infrastructure costs, and Python’s lack of static typing made every change risky. For our push notification system to be fast, we even had to develop a custom C-based service. As these issues accumulated and several deprecations loomed, we realized we needed a change.
3833

39-
Rewrites are usually a last resort, but in our case it was the only path forward. We explored a range of options like Java, Python 3, Go, and even C++. But Swift, already integral for our client apps, had great potential and a unique set of benefits: it promised excellent performance, predictable memory management through ARC, an expressive type system for reliability and maintainability, and seamless interoperability with C and C++.
34+
Rewrites are usually a last resort, but in our case, they were the only viable path for Things Cloud. We explored various programming languages including Java, Python 3, Go, and even C++. However, Swift – which was already a core part of our client apps – stood out for its potential and unique benefits. Swift promised excellent performance, predictable memory management through [ARC](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/automaticreferencecounting/), an expressive type system for reliability and maintainability, and seamless interoperability with C and C++.
4035

41-
While we had concerns that Swift on Server wasn’t as mature as other ecosystems, both Apple and the open-source community had shown strong commitment to its evolution. Swift had reliably compiled on Linux for a long time, the Swift Server Workgroup had coordinated the server efforts since 2016, the SwiftNIO library gave us confidence in the foundational capabilities, and Vapor provided all the tools to get us up and running quickly.
36+
While we initially had concerns that Swift's server support wasn’t as mature as that found in other ecosystems, both Apple and the open-source community had shown strong commitment to its evolution. Swift had reliably compiled on Linux for a long time; the Swift Server workgroup had coordinated server efforts since 2016; the [SwiftNIO library](https://github.com/apple/swift-nio) gave us confidence in the foundational capabilities, and [Vapor](https://vapor.codes) provided all the tools to get us up and running quickly.
4237

43-
Convinced by these benefits, and the prospect that it could work out well, we embarked on the rewrite. It took us three years to completely rebuild Things Cloud. We’ve been using it internally for the past two years, and it has now been live in production for almost a year.
38+
Convinced by these benefits and the opportunity to use the same language for client and server development, we embarked on a three-year journey to rewrite Things Cloud. We’ve been using it internally for the past two years, and it has now been live in production for almost a year.
4439

40+
## The new Swift server architecture
4541

46-
## What the new backend looks like
47-
48-
We’ll outline the core components of our new backend, highlighting the Swift packages we use. We’ve found that these components work well together, resulting in a reliable and stable system. We hope this serves as a valuable reference point for anyone considering a similar transition to Swift.
42+
We’ll outline the core components of our new service architecture, highlighting the Swift packages we use. We’ve found that these components work well together to provide reliability and stability, and we believe this serves as a valuable reference point for others considering a similar transition to Swift.
4943

5044
<div style="margin: 2em auto;">
5145
<img
52-
alt="Overview of our new Swift-based backend."
46+
alt="Overview of our new Swift-based back end."
5347
src="/assets/images/how-swift-on-server-powers-things-cloud-blog/new-backend-overview.png"
5448
width="840" height="525"
5549
style="max-width: 100%; width: 100%; height: auto; margin: auto; display: block;"
5650
/>
57-
<div style="text-align: center; font-style: italic; margin-top: 1em;">Overview of our new Swift-based backend.</div>
51+
<div style="text-align: center; font-size: smaller; margin-top: 1em;">Overview of our new Swift-based service architecture.</div>
5852
</div>
5953

60-
Code
61-
- Our **Swift 5.10** codebase has around 30k lines of code. It produces a binary of 60 MB, and builds in ten minutes.
54+
### Code
55+
56+
- Our **Swift** server codebase has around 30,000 lines of code. It produces a binary of 60 MB, and builds in ten minutes.
6257
- It uses **Vapor** as an HTTP web framework, which uses **SwiftNIO** as its underlying network application framework.
6358
- We compile a single “monolith” binary from our Swift source code, but use it to run multiple services, each configured by passing different parameters at runtime.
6459
- We use **Xcode** for its robust suite of tools for development, debugging, and testing. It provides us with a familiar and consistent experience across both server and client environments.
6560

66-
Deployment
61+
### Deployment
62+
6763
- **AWS** hosts our entire platform, and is entirely managed by **Terraform**, an infrastructure as code tool.
6864
- We use a continuous integration pipeline to automate tests and build our Swift code into a **Docker** image. This is then deployed in a **Kubernetes** cluster alongside other components.
6965
- The **HAProxy** load balancer is used to route client traffic to the appropriate Swift service in the cluster.
7066

71-
Storage
67+
### Storage
68+
7269
- Persistent data is stored in **Amazon Aurora MySQL**, a relational database, which we connect to with **MySQLKit**.
7370
- To keep the database small, we’re offloading less-used data to **S3**, which we access via the **Soto** package.
7471
- More ephemeral data, such as push notifications and caches, is stored in **Redis**, an in-memory key-value database, which we access via **RediStack**.
7572

76-
Other Services
73+
### Other Services
74+
7775
- The **APNSwift** package is used to communicate with the Apple Push Notification service.
7876
- **AWS Lambda**, a serverless compute service, powers our **Mail to Things** feature. This process is written in Python 3 due to its mature libraries for the processing of incoming emails. The results are passed to Swift using **Amazon Simple Queue Service**.
7977

80-
Monitoring
78+
### Monitoring
79+
8180
- We take the resilience of Things Cloud seriously and go to great lengths to ensure it.
8281
- In Swift, we generate JSON logs using our own logger. To produce metrics, we’re using the **Swift Prometheus**.
8382
- We use **Amazon CloudWatch** to store and analyze logs and metrics. It triggers Incidents, which reach the responsible engineer via **PagerDuty**.
84-
- To test how well our backend can recover from transient errors, we employ **chaos testing**. Each day, our self-written chaos agent performs random disruptive actions such as terminating a Swift service or restarting the database. We then verify that the system recovers as expected.
85-
83+
- To test how well our service can recover from transient errors, we employ **chaos testing**. Each day, our self-written chaos agent performs random disruptive actions such as terminating a Swift service or restarting the database. We then verify that the system recovers as expected.
8684

87-
## How the new backend performs
85+
## Results
8886

89-
We aimed to confirm the performance and stability of the new backend well before it reached users. So during development, we deployed the new system alongside the legacy one. While the legacy system continued to handle all requests, they were also copied over to the new system, allowing it to fully process them with its own logic and database.
87+
We wanted to thoroughly test the performance and stability of the new Swift service architecture before it was deployed in production. So during the development phase, we deployed the new system alongside the existing legacy system. While the legacy system continued to be the operational service for all requests, the new system also processed them independently using its own logic and database.
9088

91-
This approach allowed us to develop the new system under real-world conditions without risking the user experience. Gradually gaining confidence in its robustness and reliability, we were able to deploy a hardened system from day one.
89+
This approach enabled us to develop and test the new system under real-world conditions without any risk to the user experience. Thanks to the confidence we built in the new system's robustness and reliability through evaluating it with production workloads, we were able to deploy a hardened system from the very beginning.
9290

93-
Today, after a full year in production, Swift on Server has delivered on its promise. It’s fast and memory-efficient. Our Kubernetes cluster consists of four instances (each with two virtual CPUs and 8 GB of memory), and handles traffic peaking at around 500 requests per second. Compared to the legacy system, this setup has led to a more than threefold reduction in compute costs, while response times have shortened dramatically.
91+
Now, with over a full year in production, we're pleased to report that Swift has fulfilled its promise for server-side development. It’s fast and memory-efficient. Our Kubernetes cluster comprises four instances, each with two virtual CPUs and 8 GB of memory, and has handled traffic peaks of up to 500 requests per second. Compared to the legacy system, this setup has led to a more than threefold reduction in compute costs, while response times have shortened dramatically.
9492

9593
<div style="margin: 2em auto;">
9694
<img
97-
alt="Comparison between our legacy backend and new Swift-based one."
95+
alt="Comparison between our legacy back end and new Swift-based one."
9896
src="/assets/images/how-swift-on-server-powers-things-cloud-blog/performance-comparison.png"
9997
width="540" height="270"
10098
style="max-width: 100%; width: 540px; height: auto; margin: auto; display: block;"
10199
/>
102-
<div style="text-align: center; font-style: italic; margin-top: 1em;">Comparison between our legacy backend and new Swift-based one.</div>
100+
<div style="text-align: center; font-size: smaller; margin-top: 1em;">Comparison between our legacy back end and new Swift-based one.</div>
103101
</div>
104102

105-
Swift’s performance also allowed us to replace our legacy C-based push notification service with one implemented in Swift, significantly simplifying our code base and operations.
103+
And one extra win: Swift’s performance was powerful enough that we were also able to replace the custom C-based push notification service we'd built with a Swift-based one; this significantly simplified our codebase and operations.
106104

105+
## Conclusions
107106

108-
## Where we’ll go
107+
Swift turned out to be a great choice for server usage. It delivered on everything we had hoped for: We’re now using a modern and expressive programming language, the code runs and performs well, and the Swift ecosystem provides all the integrations we need. With a year of production use, we haven’t encountered a single operational issue.
109108

110-
Swift on Server turned out to be a great choice for us. It delivered on everything we had hoped for: We’re now using a modern and expressive programming language, the code runs and performs well, and the Swift ecosystem provides all the integrations we need. With a year of production use, we haven’t encountered a single operational issue.
109+
For more information on our journey and experiences, you might enjoy [our recent talk](https://youtu.be/oJArLZIQF8w?si=hLr6g5MmYH3-5K1c) at the [ServerSide.Swift](https://www.serversideswift.info) conference.
111110

112-
We encourage other teams to evaluate Swift on Server for their projects. We opted for a full rewrite, but the gradual adoption of Swift is also an interesting option, even more so with the recently announced effort around Java interoperability.
111+
We encourage other teams to consider using Swift for server-oriented projects. While we chose to undergo a complete rewrite, the gradual adoption of Swift is also an intriguing option, especially considering the recently announced initiative aimed at [enhancing Java interoperability](https://github.com/swiftlang/swift-java).
113112

114-
As for us, we consider our backend to be in the best shape it’s ever been and we’re excited about the new features we can build on this solid foundation.
113+
As for us, we believe our server architecture is in its best shape ever, and we’re thrilled about the new features we can build upon this solid foundation.

0 commit comments

Comments
 (0)