i think server encompasses a huge range of very different types of applications, so when i hear “this is how it works” i try to read an implicit within the problem domain that i spend most of my time working on.
Yeah, would be nice to have a way to execute some things in isolated memory space.
agreed. I did not take it any other way ; )
Also, I am not even disagreeing with @Helge_Hess1. Many times things will be just fine if you somehow manage to wind down a bit more elegantly rather than crash on the spot.
But, to me, it is a bit like saying "accessing this shared state is fine, I have the threading under control", and then you end up having the weirdest, most difficult to find issues with data races.
Unless there are some compile-time and/or runtime guarantees that things are not messed up beyond repair after an undefined op, crashing is a fine solution in my book.
Any other pain points for Swift Server applications that aren't related to crash isolation?
Say more, is the issue in your view that Swift uses ARC on the server, or that ARC is fine, but the tools to help debug retain cycles should be easier to use for server deployments? Or something else?
to compare notes, here’s what i am currently doing
i currently do not use swiftly, i just use Docker for my development environment.
i currently use SwiftPM, as there is no real alternative to it. i believe there is broad consensus on what the missing pieces in SwiftPM are but for note-keeping i’ll list them below:
- no support for shallow git clone
- cannot build app in debug mode but dependencies in release mode
- cannot use pre-built dependencies
- does not check for explicit target dependency by default, still requires a long-winded command line flag that i can never remember the spelling of
- cache invalidation for local package dependencies doesn’t seem to work very reliably at the moment
i currently avoid both, but largely because they increase binary size by a lot, which also increases baseline memory consumption by the same amount.
the platform portability aspect is less important to me, mostly because a lot of this code is server-specific and therefore Linux-only.
the swift-async-algorithms package has a similar issue, which i currently solve by just copying and pasting the source code of the AsyncChannel implementation into my projects.
i currently use ArraySlice<UInt8> everywhere. it really works!
i use Docker to deploy, which took me a long time to figure out but it’s pretty nice once you’ve got it set up. sadly, this stuff is sparsely documented, especially the cross-compilation aspect, and i only figured it out because many kind folks on these Forums spent time helping me.
i believe we as a project need to consider documentation as a blocking requirement for evolution proposals, as we have gotten into the habit of shipping a lot of complex features while treating the educational aspect as an afterthought.
i use VSCode ![]()
i write and maintain a lot of my own libraries, and open-source many of them. but obviously that’s not a scalable practice. we need to see more (financial!) investment from Apple in the library ecosystem.
I host multiple Swift servers in production on a locally hosted Arch Linux machine, and develop using VSCode & SwiftPM on an Arch Linux machine.
I used to main macOS with Xcode for the development of my servers and open-source projects, but there were way too many variables to consider for cross deployment (personally I've had problems with variations of: clang, gcc, Swift, llvm, different installed compilers, different tooling) that resulted in the servers crashing daily, but not once on macOS, while deploying the same code! Swift has gotten better on Linux, and in general, in this regard the past 2 years.
Like others have pointed out, server resilience is the main pain point of Swift on Server. Using safer techniques when parsing/sanitizing input data eliminated all my crashes, but I had to manually create those solutions.
With Swift 6 it is a lot easier to fix problems relating to memory access (at least in my experience). Perhaps more compilation errors/warnings should be added to detect possible crashes relating to integer overflows and manipulating decoded data. Third-party libraries can do this, albeit in a very limited capacity, utilizing Swift Macros and diagnostic messages.
In summary, my pain points for deploying Swift on Server are:
- different code behavior on macOS than Linux (especially when working with unsafe pointers; irrelevant if developing & deploying on Linux)
- crashes relating to integer overflow or input decoding require manual solution to avoid crashing
- bloated dependencies (not really a problem, but adds unnecessary compilation time; SwiftPM will be getting better at this in the future; my precious uptime...)
- great libraries and Swift/Apple features not being cross-platform (data compression, localization)
- great libraries in other languages needing a Swift compatibility layer, if they don't already have one
- lack of standalone libraries (or any library) for creating websites, managing databases, server networking, data compression, localization, and region subdivisions
There are way more points that make Swift excellent for applications, even for servers. The only real competitor in this space that I see is Rust, but Swift is way easier to use and understand syntactically.
I'm actively developing open-source standalone libraries for my pain points
- Websites: Swift HTMLKit
- Databases: Swift Database
- Server Networking: Destiny
- Data Compression: Swift Compression
- Localization: Swift String Catalogs
- Region Subdivisions: Swift Sovereign States
are there compression algorithms you would like to use in Swift, but don’t have library support?
Well, all of the best/well known ones out there. It’s not really the lack of library support, but more of doing it well. Like there is always a tradeoff, whether it be implementation, lacking customization or not being standalone. I'd much rather have a single library that does them all, or a few libraries focused on a single compression area (one for SSL, one for images & video, one for text and similar data, etc).
This gripe is mainly based on the Compression framework not being available on Linux and some good libraries not being standalone (pulls in a large dependency that I won't use).
Just to name a few: huffman coding, brotli, deflate, jpeg, h.264 & h.265, gzip, zstd, lz + variants, 7Z, RAR, DNAC-SBE, json compression, bzip2, botan, boringssl, openssl, s2n-tls.
have you looked at swift-png yet? it implements the LZ77 algorithm and the Gzip format, which is just a wrapper around an LZ77 algorithm. LZ77 and DEFLATE are also the same thing.
i have also written the swift-jpeg library for the JPEG format
I am trying something like this there, maybe others might join the efforts (or write something better). (UPDATE: I started a separate topic on this.) But this has overhead.
Well, I think it is also about selling your application (in cases where it is not you who is actually running it). The customer might want to run only one instance (maybe as a first deployment), and telling the customer that a failure in a single request might crash the whole application is not a good selling point.
Sorry for quoting myself, but maybe one of the compiler people could comment this, would be interesting to know. Thanks.
Yes, the discussion about this point got big here, could better be a topic on its own. But it seems to be a major pain point for some people (including me).
UPDATE: I started a separate topic on this.
It can be potentially, even with language features, but with a bit of work. That what I meant, a bit of hack though of course:
And was wondering maybe there are other ideas.
Probably naive question (not 100% sure how SwiftNIO works under hood, need to check finally), but is there a reason not to make this single process isolated? When it crashes then SwiftNIO can inform whoever and recreate to process.
SwiftNIO not (yet) running on Windows is an issue. Of course, “a real server application runs on Linux”, but you might want to run a server application locally on your machine, be it for development or deployment.
Here are some of the pain points I've hit recently for Swift on the server:
- FoundationEssentials - my current hill to die on
. Trying to use this when developing on macOS and deploying on Linux is a case of trial and error and really sours the experience when trying to adopt new Foundation and remove binary sizes - Linking issues - this has been a perpetual issue in Swift for some years and improvements were made back in 5.9/5.10 but do appeared to have regressed in Swift 6. The linker is extremely memory hungry and makes it hard to build Swift applications on memory constrained environments. Especially Heroku build packs, and those developing on an old-school approach for a VPS which both compiles and hosts the application. It would be great to have these regressions investigated and fixed
- General build times. Swift is always going to struggle to compete against interpreted languages when it comes to build times but comparisons to other compiled languages like Go are pretty stark. I think we could do better as a community at offering solutions for SwiftPM caches in CI etc and it would be great to see things like dependency caching be a thing.
- Formatting stack traces - systems like Google Stackdriver logging have strict requirements in the format of logs. Before backtrace was built in we could attach signal handlers, manually capture a backtrace, log it however we want and then crash out. This is no longer possible and the backtrace runtime currently doesn't allow us to format the logs. This is a pretty minor issue however, just one I've hit recently in an app migration.
Personally I've had very few issues with applications crashing in live (part of the reason why I'm not hugely concerned with the last point). Especially since we've adopted Sendable there have been a marked drop in reported crashes and generally things are pretty stable.
any reasons you are not using Docker with VSCode devcontainers?
That is our experience and it works pretty well now after the foundation merge in 6.0. The major difference which can cause problems in our experience is the slightly subpar implementation of the concurrency runtime for lib dispatch on Linux compared to macOS. Hopefully we’ll see closer parity there in the future.
I'll actually add FoundationXML and FoundationNetworking to this list. It's easier than essentials since the boundary is well understood and defined, but it's still confusing to new comers to the language and would be great to include
Using Swift on the server is only possible when your server platform of choice is supported by Swift. The supported platforms are Linux, Windows and macOS (theoretically it is a server OS too). People who love and trust other highly-capable server operating systems like FreeBSD can choose between:
- Not using Swift
- Not using their server platform of choice
I think the choice is easy.
@doctorj I hope I’m not too late, but you know holidays. I’ve been running several Swift on the server components and here are my top 4:
-
Build times, compute and memory footprint during build are astronomical. Swift components are costing us 3x more than JVM/Kotlin components and 10x more than Rust/Go components to build. It’s really quite expensive to run Swift on the server.
-
Limited supported platforms e.g. what about Debian or BSD or Fedora etc. It’s also misleading that development and production platforms are not the same. Creating custom Docker images is not easy with dependencies, build times, and the resulting image sizes are gigantic - we actually pay for storage and egress for our container repositories.
-
Developing for the server on macOS is a huge pain in two main areas: 1) the overlapping types with iOS/macOS frameworks (e.g. Crypto) makes it impossible to know if what builds on macOS will build and even run on some Linux environment. Others have already mentioned the pain of FoundationEssentials, networking etc. 2) As a result of the previous, the ecosystem of Swift packages is full of libraries which although claiming support for server/linux targets, do not actually (correctly) support that.
-
DX around tooling has many papercuts (we see this when onboarding devs coming from more established server language ecosystems). One very prominent point is, well, IDE - Xcode is great for apps but positively hostile for server apps. There is VSCode but beyond that it’s hard to configure proper language server support (e.g. say one is using Zed, or vim/emacs inspired setup), get hints about supported targets for specific functions, running tests, visualising test results in existing systems, integrating with vulnerability/security scanning tools etc.