From 595a73c5ce7fbad6cea9206a4c0aa4565b993cf4 Mon Sep 17 00:00:00 2001 From: Vojtech Rylko Date: Thu, 14 Nov 2024 16:18:56 +0100 Subject: [PATCH 1/7] Add blog post "How Swift on Server powers Things Cloud" --- _data/authors.yml | 12 +- ...how-swift-on-server-powers-things-cloud.md | 114 ++++++++++++++++++ .../new-backend-overview.png | Bin 0 -> 50633 bytes .../performance-comparison.png | Bin 0 -> 12773 bytes .../things-cloud-with-devices.png | Bin 0 -> 19155 bytes .../things-logo.png | Bin 0 -> 10301 bytes 6 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 _posts/2024-12-01-how-swift-on-server-powers-things-cloud.md create mode 100644 assets/images/how-swift-on-server-powers-things-cloud-blog/new-backend-overview.png create mode 100644 assets/images/how-swift-on-server-powers-things-cloud-blog/performance-comparison.png create mode 100644 assets/images/how-swift-on-server-powers-things-cloud-blog/things-cloud-with-devices.png create mode 100644 assets/images/how-swift-on-server-powers-things-cloud-blog/things-logo.png diff --git a/_data/authors.yml b/_data/authors.yml index 3dba07ba3..4caa0629a 100644 --- a/_data/authors.yml +++ b/_data/authors.yml @@ -479,4 +479,14 @@ owen-voorhees: adam-ward: name: Adam Ward - about: "Adam Ward is a member of the team at Apple working on Swift tooling." \ No newline at end of file + about: "Adam Ward is a member of the team at Apple working on Swift tooling." + +vrylko: + name: Vojtěch Rylko + github: vojtarylko + about: "Vojtěch Rylko is responsible for development and operations of Things Cloud at Cultured Code." + +wjainek: + name: Werner Jainek + github: wjainek + about: "Werner Jainek is Co-Founder and CEO at Cultured Code." diff --git a/_posts/2024-12-01-how-swift-on-server-powers-things-cloud.md b/_posts/2024-12-01-how-swift-on-server-powers-things-cloud.md new file mode 100644 index 000000000..3e72ec14d --- /dev/null +++ b/_posts/2024-12-01-how-swift-on-server-powers-things-cloud.md @@ -0,0 +1,114 @@ +--- +layout: post +published: true +date: 2024-12-01 10:00:00 +title: How Swift on Server powers Things Cloud +author: [vrylko, wjainek] +--- + +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. + +*Note: This article is an adaptation of [our recent talk](https://youtu.be/oJArLZIQF8w?si=hLr6g5MmYH3-5K1c) at the Server-Side Swift Conference.* + +Things logo + +[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. + +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. + +
+ Things Cloud synchronizes to-dos across different devices. +
Things Cloud synchronizes to-dos across different devices.
+
+ + +## Why we switched to Swift + +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. + +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++. + +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. + +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. + + +## What the new backend looks like + +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. + +
+ Overview of our new Swift-based backend. +
Overview of our new Swift-based backend.
+
+ +Code +- Our **Swift 5.10** codebase has around 30k lines of code. It produces a binary of 60 MB, and builds in ten minutes. +- It uses **Vapor** as an HTTP web framework, which uses **SwiftNIO** as its underlying network application framework. +- 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. +- 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. + +Deployment +- **AWS** hosts our entire platform, and is entirely managed by **Terraform**, an infrastructure as code tool. +- 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. +- The **HAProxy** load balancer is used to route client traffic to the appropriate Swift service in the cluster. + +Storage +- Persistent data is stored in **Amazon Aurora MySQL**, a relational database, which we connect to with **MySQLKit**. +- To keep the database small, we’re offloading less-used data to **S3**, which we access via the **Soto** package. +- More ephemeral data, such as push notifications and caches, is stored in **Redis**, an in-memory key-value database, which we access via **RediStack**. + +Other Services +- The **APNSwift** package is used to communicate with the Apple Push Notification service. +- **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**. + +Monitoring +- We take the resilience of Things Cloud seriously and go to great lengths to ensure it. +- In Swift, we generate JSON logs using our own logger. To produce metrics, we’re using the **Swift Prometheus**. +- We use **Amazon CloudWatch** to store and analyze logs and metrics. It triggers Incidents, which reach the responsible engineer via **PagerDuty**. +- 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. + + +## How the new backend performs + +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. + +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. + +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. + +
+ Comparison between our legacy backend and new Swift-based one. +
Comparison between our legacy backend and new Swift-based one.
+
+ +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. + + +## Where we’ll go + +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. + +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. + +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. diff --git a/assets/images/how-swift-on-server-powers-things-cloud-blog/new-backend-overview.png b/assets/images/how-swift-on-server-powers-things-cloud-blog/new-backend-overview.png new file mode 100644 index 0000000000000000000000000000000000000000..a741f0f1c84127b91470c11b78e0c89a35ad200f GIT binary patch literal 50633 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ɖP-}~3>!A=> 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 literal 0 HcmV?d00001 diff --git a/assets/images/how-swift-on-server-powers-things-cloud-blog/performance-comparison.png b/assets/images/how-swift-on-server-powers-things-cloud-blog/performance-comparison.png new file mode 100644 index 0000000000000000000000000000000000000000..17f815c9c73861976c5da04b35a2f40261c2b865 GIT binary patch literal 12773 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 z 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 literal 0 HcmV?d00001 diff --git a/assets/images/how-swift-on-server-powers-things-cloud-blog/things-cloud-with-devices.png b/assets/images/how-swift-on-server-powers-things-cloud-blog/things-cloud-with-devices.png new file mode 100644 index 0000000000000000000000000000000000000000..15403a272a62fdf748bfe108e52be45a5596fdce GIT binary patch literal 19155 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 L8{?OT1mgbztw7PP literal 0 HcmV?d00001 From e7dea7ee494a052ea27f24b91ac1175edf4bc504 Mon Sep 17 00:00:00 2001 From: Tim Sneath Date: Thu, 13 Feb 2025 15:02:53 -0800 Subject: [PATCH 2/7] Full copy edit --- Gemfile.lock | 34 ++++---- ...how-swift-on-server-powers-things-cloud.md | 77 +++++++++---------- 2 files changed, 55 insertions(+), 56 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index f508b7ae9..e49c6b715 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -12,34 +12,34 @@ GEM eventmachine (>= 0.12.9) http_parser.rb (~> 0) eventmachine (1.2.7) - ffi (1.17.0) - ffi (1.17.0-aarch64-linux-gnu) - ffi (1.17.0-aarch64-linux-musl) - ffi (1.17.0-arm-linux-gnu) - ffi (1.17.0-arm-linux-musl) - ffi (1.17.0-arm64-darwin) - ffi (1.17.0-x86-linux-gnu) - ffi (1.17.0-x86-linux-musl) - ffi (1.17.0-x86_64-darwin) - ffi (1.17.0-x86_64-linux-gnu) - ffi (1.17.0-x86_64-linux-musl) + ffi (1.17.1) + ffi (1.17.1-aarch64-linux-gnu) + ffi (1.17.1-aarch64-linux-musl) + ffi (1.17.1-arm-linux-gnu) + ffi (1.17.1-arm-linux-musl) + ffi (1.17.1-arm64-darwin) + ffi (1.17.1-x86-linux-gnu) + ffi (1.17.1-x86-linux-musl) + ffi (1.17.1-x86_64-darwin) + ffi (1.17.1-x86_64-linux-gnu) + ffi (1.17.1-x86_64-linux-musl) forwardable-extended (2.6.0) - google-protobuf (4.28.3) + google-protobuf (4.29.3) bigdecimal rake (>= 13) - google-protobuf (4.28.3-aarch64-linux) + google-protobuf (4.29.3-aarch64-linux) bigdecimal rake (>= 13) - google-protobuf (4.28.3-arm64-darwin) + google-protobuf (4.29.3-arm64-darwin) bigdecimal rake (>= 13) - google-protobuf (4.28.3-x86-linux) + google-protobuf (4.29.3-x86-linux) bigdecimal rake (>= 13) - google-protobuf (4.28.3-x86_64-darwin) + google-protobuf (4.29.3-x86_64-darwin) bigdecimal rake (>= 13) - google-protobuf (4.28.3-x86_64-linux) + google-protobuf (4.29.3-x86_64-linux) bigdecimal rake (>= 13) http_parser.rb (0.8.0) diff --git a/_posts/2024-12-01-how-swift-on-server-powers-things-cloud.md b/_posts/2024-12-01-how-swift-on-server-powers-things-cloud.md index 3e72ec14d..98cc277b4 100644 --- a/_posts/2024-12-01-how-swift-on-server-powers-things-cloud.md +++ b/_posts/2024-12-01-how-swift-on-server-powers-things-cloud.md @@ -1,14 +1,12 @@ --- layout: post published: true -date: 2024-12-01 10:00:00 -title: How Swift on Server powers Things Cloud +date: 2025-02-21 10:00:00 +title: How Swift's Server Support powers Things Cloud author: [vrylko, wjainek] --- -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. - -*Note: This article is an adaptation of [our recent talk](https://youtu.be/oJArLZIQF8w?si=hLr6g5MmYH3-5K1c) at the Server-Side Swift Conference.* +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. Things logo -[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. - -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. +[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.

-
Things Cloud synchronizes to-dos across different devices.
+
Things Cloud synchronizes to-dos across different devices.
+## Switching to Swift -## Why we switched to Swift - -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. +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. -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++. +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++. -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. +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. -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. +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. +## The new Swift server architecture -## What the new backend looks like - -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. +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.
Overview of our new Swift-based backend. -
Overview of our new Swift-based backend.
+
Overview of our new Swift-based service architecture.
-Code -- Our **Swift 5.10** codebase has around 30k lines of code. It produces a binary of 60 MB, and builds in ten minutes. +### Code + +- Our **Swift** server codebase has around 30,000 lines of code. It produces a binary of 60 MB, and builds in ten minutes. - It uses **Vapor** as an HTTP web framework, which uses **SwiftNIO** as its underlying network application framework. - 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. - 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. -Deployment +### Deployment + - **AWS** hosts our entire platform, and is entirely managed by **Terraform**, an infrastructure as code tool. - 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. - The **HAProxy** load balancer is used to route client traffic to the appropriate Swift service in the cluster. -Storage +### Storage + - Persistent data is stored in **Amazon Aurora MySQL**, a relational database, which we connect to with **MySQLKit**. - To keep the database small, we’re offloading less-used data to **S3**, which we access via the **Soto** package. - More ephemeral data, such as push notifications and caches, is stored in **Redis**, an in-memory key-value database, which we access via **RediStack**. -Other Services +### Other Services + - The **APNSwift** package is used to communicate with the Apple Push Notification service. - **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**. -Monitoring +### Monitoring + - We take the resilience of Things Cloud seriously and go to great lengths to ensure it. - In Swift, we generate JSON logs using our own logger. To produce metrics, we’re using the **Swift Prometheus**. - We use **Amazon CloudWatch** to store and analyze logs and metrics. It triggers Incidents, which reach the responsible engineer via **PagerDuty**. -- 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. - +- 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. -## How the new backend performs +## Results -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. +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. -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. +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. -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. +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.
Comparison between our legacy backend and new Swift-based one. -
Comparison between our legacy backend and new Swift-based one.
+
Comparison between our legacy back end and new Swift-based one.
-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. +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. +## Conclusions -## Where we’ll go +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. -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. +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. -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. +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). -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. +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. From 33a3b9ae4590da5c5008d7f3714e6e3006325436 Mon Sep 17 00:00:00 2001 From: Tim Sneath Date: Thu, 13 Feb 2025 15:03:22 -0800 Subject: [PATCH 3/7] Rename blog post --- ...d.md => 2025-02-21-how-swift-on-server-powers-things-cloud.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename _posts/{2024-12-01-how-swift-on-server-powers-things-cloud.md => 2025-02-21-how-swift-on-server-powers-things-cloud.md} (100%) diff --git a/_posts/2024-12-01-how-swift-on-server-powers-things-cloud.md b/_posts/2025-02-21-how-swift-on-server-powers-things-cloud.md similarity index 100% rename from _posts/2024-12-01-how-swift-on-server-powers-things-cloud.md rename to _posts/2025-02-21-how-swift-on-server-powers-things-cloud.md From 5570e4263cf541353916bb44dfb489d475db96f8 Mon Sep 17 00:00:00 2001 From: Vojtech Rylko Date: Fri, 14 Feb 2025 17:04:50 +0100 Subject: [PATCH 4/7] Small tweaks --- ...-how-swift-on-server-powers-things-cloud.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/_posts/2025-02-21-how-swift-on-server-powers-things-cloud.md b/_posts/2025-02-21-how-swift-on-server-powers-things-cloud.md index 98cc277b4..c5755f48d 100644 --- a/_posts/2025-02-21-how-swift-on-server-powers-things-cloud.md +++ b/_posts/2025-02-21-how-swift-on-server-powers-things-cloud.md @@ -2,11 +2,11 @@ layout: post published: true date: 2025-02-21 10:00:00 -title: How Swift's Server Support powers Things Cloud +title: How Swift's server support powers Things Cloud author: [vrylko, wjainek] --- -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. +You might be familiar with [Things](https://culturedcode.com/things/), a delightful personal task manager that has won two 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. Things logo Overview of our new Swift-based back end. Comparison between our legacy back end and new Swift-based one. -
Comparison between our legacy back end and new Swift-based one.
+
Comparison between our legacy service and new Swift-based one.
-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. +And one extra win: Swift’s outstanding performance allowed us to replace our custom C-based push notification service with a Swift-based one; this significantly simplified our codebase and operations. ## Conclusions From 537a6b964a0f6ad422624ff1b4a928d499dc6727 Mon Sep 17 00:00:00 2001 From: Vojtech Rylko Date: Fri, 14 Feb 2025 17:44:44 +0100 Subject: [PATCH 5/7] Reflect the new blog post title in the file name --- ...> 2025-02-21-how-swifts-server-support-powers-things-cloud.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename _posts/{2025-02-21-how-swift-on-server-powers-things-cloud.md => 2025-02-21-how-swifts-server-support-powers-things-cloud.md} (100%) diff --git a/_posts/2025-02-21-how-swift-on-server-powers-things-cloud.md b/_posts/2025-02-21-how-swifts-server-support-powers-things-cloud.md similarity index 100% rename from _posts/2025-02-21-how-swift-on-server-powers-things-cloud.md rename to _posts/2025-02-21-how-swifts-server-support-powers-things-cloud.md From d5727dacbfe735f250bae3d68b144b136838fa23 Mon Sep 17 00:00:00 2001 From: Vojtech Rylko Date: Fri, 14 Feb 2025 18:48:32 +0100 Subject: [PATCH 6/7] Reflect the new blog post title also in the assets folder --- ...how-swifts-server-support-powers-things-cloud.md | 8 ++++---- .../new-backend-overview.png | Bin .../performance-comparison.png | Bin .../things-cloud-with-devices.png | Bin .../things-logo.png | Bin 5 files changed, 4 insertions(+), 4 deletions(-) rename assets/images/{how-swift-on-server-powers-things-cloud-blog => how-swifts-server-support-powers-things-cloud}/new-backend-overview.png (100%) rename assets/images/{how-swift-on-server-powers-things-cloud-blog => how-swifts-server-support-powers-things-cloud}/performance-comparison.png (100%) rename assets/images/{how-swift-on-server-powers-things-cloud-blog => how-swifts-server-support-powers-things-cloud}/things-cloud-with-devices.png (100%) rename assets/images/{how-swift-on-server-powers-things-cloud-blog => how-swifts-server-support-powers-things-cloud}/things-logo.png (100%) diff --git a/_posts/2025-02-21-how-swifts-server-support-powers-things-cloud.md b/_posts/2025-02-21-how-swifts-server-support-powers-things-cloud.md index c5755f48d..162e12183 100644 --- a/_posts/2025-02-21-how-swifts-server-support-powers-things-cloud.md +++ b/_posts/2025-02-21-how-swifts-server-support-powers-things-cloud.md @@ -10,7 +10,7 @@ You might be familiar with [Things](https://culturedcode.com/things/), a delight Things logo @@ -20,7 +20,7 @@ You might be familiar with [Things](https://culturedcode.com/things/), a delight
Things Cloud synchronizes to-dos across different devices. @@ -44,7 +44,7 @@ We’ll outline the core components of our new service architecture, highlightin
Overview of our new Swift-based service architecture. @@ -93,7 +93,7 @@ Now, with over a full year in production, we're pleased to report that Swift has
Comparison between our legacy service and new Swift-based one. diff --git a/assets/images/how-swift-on-server-powers-things-cloud-blog/new-backend-overview.png b/assets/images/how-swifts-server-support-powers-things-cloud/new-backend-overview.png similarity index 100% rename from assets/images/how-swift-on-server-powers-things-cloud-blog/new-backend-overview.png rename to assets/images/how-swifts-server-support-powers-things-cloud/new-backend-overview.png diff --git a/assets/images/how-swift-on-server-powers-things-cloud-blog/performance-comparison.png b/assets/images/how-swifts-server-support-powers-things-cloud/performance-comparison.png similarity index 100% rename from assets/images/how-swift-on-server-powers-things-cloud-blog/performance-comparison.png rename to assets/images/how-swifts-server-support-powers-things-cloud/performance-comparison.png diff --git a/assets/images/how-swift-on-server-powers-things-cloud-blog/things-cloud-with-devices.png b/assets/images/how-swifts-server-support-powers-things-cloud/things-cloud-with-devices.png similarity index 100% rename from assets/images/how-swift-on-server-powers-things-cloud-blog/things-cloud-with-devices.png rename to assets/images/how-swifts-server-support-powers-things-cloud/things-cloud-with-devices.png diff --git a/assets/images/how-swift-on-server-powers-things-cloud-blog/things-logo.png b/assets/images/how-swifts-server-support-powers-things-cloud/things-logo.png similarity index 100% rename from assets/images/how-swift-on-server-powers-things-cloud-blog/things-logo.png rename to assets/images/how-swifts-server-support-powers-things-cloud/things-logo.png From c67ed533da22d814a44d319cf61c0b39cb08ccb3 Mon Sep 17 00:00:00 2001 From: Tim Sneath Date: Tue, 18 Feb 2025 12:37:18 -0800 Subject: [PATCH 7/7] Revert Gemfile back to main --- Gemfile.lock | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index e49c6b715..a68834ebc 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -12,34 +12,34 @@ GEM eventmachine (>= 0.12.9) http_parser.rb (~> 0) eventmachine (1.2.7) - ffi (1.17.1) - ffi (1.17.1-aarch64-linux-gnu) - ffi (1.17.1-aarch64-linux-musl) - ffi (1.17.1-arm-linux-gnu) - ffi (1.17.1-arm-linux-musl) - ffi (1.17.1-arm64-darwin) - ffi (1.17.1-x86-linux-gnu) - ffi (1.17.1-x86-linux-musl) - ffi (1.17.1-x86_64-darwin) - ffi (1.17.1-x86_64-linux-gnu) - ffi (1.17.1-x86_64-linux-musl) + ffi (1.17.0) + ffi (1.17.0-aarch64-linux-gnu) + ffi (1.17.0-aarch64-linux-musl) + ffi (1.17.0-arm-linux-gnu) + ffi (1.17.0-arm-linux-musl) + ffi (1.17.0-arm64-darwin) + ffi (1.17.0-x86-linux-gnu) + ffi (1.17.0-x86-linux-musl) + ffi (1.17.0-x86_64-darwin) + ffi (1.17.0-x86_64-linux-gnu) + ffi (1.17.0-x86_64-linux-musl) forwardable-extended (2.6.0) - google-protobuf (4.29.3) + google-protobuf (4.28.3) bigdecimal rake (>= 13) - google-protobuf (4.29.3-aarch64-linux) + google-protobuf (4.28.3-aarch64-linux) bigdecimal rake (>= 13) - google-protobuf (4.29.3-arm64-darwin) + google-protobuf (4.28.3-arm64-darwin) bigdecimal rake (>= 13) - google-protobuf (4.29.3-x86-linux) + google-protobuf (4.28.3-x86-linux) bigdecimal rake (>= 13) - google-protobuf (4.29.3-x86_64-darwin) + google-protobuf (4.28.3-x86_64-darwin) bigdecimal rake (>= 13) - google-protobuf (4.29.3-x86_64-linux) + google-protobuf (4.28.3-x86_64-linux) bigdecimal rake (>= 13) http_parser.rb (0.8.0) @@ -174,4 +174,4 @@ DEPENDENCIES webrick (~> 1.7) BUNDLED WITH - 2.5.23 + 2.5.23 \ No newline at end of file