Hacker News new | past | comments | ask | show | jobs | submit login
Swift AWS Lambda Runtime (swift.org)
223 points by NobodyNada 7 months ago | hide | past | favorite | 79 comments

Is there any recent rundown on the state of server-side Swift in general? I know there was a lot of discussion when IBM stopped working on it back in January.

At the broadest level, I wonder what the footprint of Swift at runtime is, both in terms of CPU and RAM. I've been really enjoying Kotlin as a server-side language - it's a massive step up in productivity from TypeScript - but the overhead of the JVM certainly is notable, even in small personal projects (my small Javalin app uses four times the RAM at rest as my Express app did). Swift is really interesting to me because it is very similar in practice to Kotlin, but with some very cool and powerful additional language features. So, if server-side Swift has a smaller footprint at runtime and equal or better performance than Kotlin on the JVM[1], that'd be a really compelling language for me.

[1] yes, I know GraalVM/native options exist for Kotlin, but every time I've tried to investigate ecosystem compatibility, it leads to me glancing at pages long-articles about "how to configure X framework for GraalVM" that make it not seem worth the effort yet

Here’s a quick summary of things - https://www.timc.dev/posts/future-of-server-side-swift

Blog posts that are time-relevant should really be dated.

This one is very interesting and unexpected. Swift for TensorFlow: The Next-Generation Machine Learning Framework: https://www.youtube.com/watch?v=s65BigoMV_I

anyone using it yet?

I would doubt it! Macs aren't sold with NVIDIA cards, so I'd guess the support for them would be poor, if available at all. I don't think Swift has full releases to Windows or Linux yet?

Fast.ai and the likes have been investigating Swift too, so there's some momentum/ desire to switch to Swift.

I don't believe it will go anywhere, Fortran, C++, Python and Julia are what matters in GPGPU.

Even Java and .NET have better support for CUDA than Swift ever will.

> my small Javalin app uses four times the RAM at rest as my Express app did

Are you looking at used heap space or just the amount of memory used by the Java process? I have a few small Java services using vert.x and they hover around 7-15 MB of used heap space. For small services I usually just restrict the maximum heap space size because the default is unnecessarily large.

What about Kotlin make it a step above typescript in terms of productivity?

This is a blog post I've been putting off writing for a while; I'll try to tl;dr it best I can given it's somewhat off-topic:

* TypeScript's lack of runtime types and stable reflection APIs make it hard to have any guarantees of type soundness without either code generation (e.g. schemats) or complex type programming to convert a runtime representation of a type to a static type (e.g. io-ts). I find this very frustrating when doing web backend programming, where you are constantly doing i/o with external services (whether HTTP APIs, or input from client requests, or database interaction).

This is particularly maddening because there's no de facto standards (seriously, there are a lot of these libraries: https://github.com/moltar/typescript-runtime-type-benchmarks), so it's not easy to e.g. find a DB library that will let you define an io-ts schema that a query should match without re-wrapping things yourself.

Basically: if TypeScript had runtime types, and an `as` cast threw an exception when a value doesn't match the specified type, I'd be much more inclined to keep using it. I genuinely think that's table stakes for a type safe language.

(and lest you think this has to be how TS works given the nature of how it's compiled to vanilla JS, I suggest you take a peek at Sorbet, which knew this was necessary: https://sorbet.org/docs/runtime)

* The TS ecosystem is generally underwhelming. I don't think any HTTP framework for it is particularly good, nor any ORM/query builder. I think there are a lot of really neat experiments still happening in this space, and it seems like every day GitHub's little "explore repositories" sidebar shows me another cool library someone's built for TS trying to solve some of these problems, but it's all early stage stuff with a bus factor of 1 and a long todo list.

To be fair, _Kotlin's_ ecosystem actually has a lot of these problems; the semi-official Jetbrains-maintained Kotlin web framework and DB access library both have a ton of untriaged issues and seemingly little production use. The good news is, at least on the server, you can completely ignore the "Kotlin" ecosystem in favor of the Java ecosystem, and this is _shockingly_ effective. Just about every JVM framework I've seen has some kind of officially-maintained Kotlin adapter, presumedly because it's not hard to sell Java developers on "what if you could keep using the exact same tools with a nicer language." These adapters aren't even needed, mind you, they just provide nicer APIs that can use Kotlin language features. Javalin + JDBI is infinitely nicer out of the box than trying to turn Express and Knex into a production-ready API with anything approaching type safety.

* This isn't a make-or-break thing, but Kotlin is just generally _nicer_ than JS or TS in a lot of ways, while still having a very similar programming style. For example, the collection types are far more robust than something like Lodash (let alone the absolute joke that is the ES6 Map/Set API).

I actually went back and forth with these exact same options recently. To the extent any of this is helpful:

* Agreed with the problem, although I've found io-ts to be great. For incoming client requests: GraphQL is helpful if you're using that, but it's also relatively trivial to create an io-ts middleware for express that will get you similar guarantees. For database interaction, assuming you're talking about relational data stores, this is a challenge. Personally, I'm using Mikro ORM and it has been great so far. The one blessing here is that you're probably not dealing with unknown data types when talking to a data store, so it hasn't felt like as much of a concerning surface area for me personally. HTTP is valid, but I actually like io-ts as an approach here possibly more than using Jackson with static types due to its failure model - but again I acknowledge this is a personal choice.

* I guess it depends on your needs here, but base express can be great for simple apps, and NestJS is fantastic for more complex ones. You're 100% on point with ORMs, though, where I've been incredibly dissatisfied generally. As mentioned above, I've recently stumbled on Mikro ORM which takes a unit of work pattern similar to Hibernate, without the painful startup time. You can tell it's not perfect, and certainly not as feature rich as Hibernate, but also feels safe enough. I imagine if you tried to do everything through the ORM it could get painful, but most of my apps are structured as multiple modules where each module only controls the entities within that module. It keeps the reach of the ORM limited and abstracted behind "services" (in the modular monolith sense, not remote services).

* Yeah I see both ends of this one. Historically been a JVM user and have a ton of appreciation for it, but also like TS's approach more than Kotlin in several ways. You're right about collections though, ES6 is a joke there.

Strongly agreed. I'll add that Typescript in general just has way more rough edges than Kotlin, in part because the type system is way more complex (due to the dynamic nature of Javascript). And dealing with third party libraries is way more of a pain, since everything requires type stubs.

Probably one of the best, recent overviews of Swift on the server is by Tim Condon [0]. TLDR: nightly Docker images of Swift, shared libs (Swift Crypto an example), more Linux distros supported, Amazon's 2.0 release of Smoke [1] (which is probably involved in this runtime), all indicate that Swift's future on the server is probably bright, even if it is still early.

[0] - https://www.timc.dev/posts/future-of-server-side-swift

[1] - https://github.com/amzn/smoke-framework

Chalk one up for time wasted not addressing what people really need...

I truly love Swift, like god-damn is it my cup of tea, but I can't really bring myself to write it anymore. I've written over 10,000+ lines , shipped and maintained a few different production apps, but anymore I just have no urge to write it.

And the biggest reason why? I think it being open source is a joke until Apple, and I mean Apple themselves, implements some sort of cross-platform UI framework with it. Like, most of what is written in Swift is fucking UI code that's totally useless on other platforms.

I think it's pretty laughable I can run Swift on AWS but I can't do a simple GUI app on Linux or Windows using the OOB Swift SDK. Apple, you're a fucking trillion dollar organization, for fucks sake stop being so damn stingy with portability.

When I can write cross-platform GUI apps with Swift, maybe I'll give a fuck 'bout running it on a server. Just my two very bitter, hurt, and sad two cents...

A good, modern, general purpose cross-platform GUI application framework is a very different proposition than server-side Swift. It’s also a very, very tall order that would require a lot of resources to create and a lot more to maintain... and I don’t see big strategic benefits to Apple in doing so.

I don’t think it’s going to happen.

Maybe WASM will lead to browser-side Swift and then you can do Electron-style cross platform apps using web technologies. (Not that I think Apple would put resources to that either.)

> Chalk one up for time wasted not addressing what people really need...

As a Swift programmer, I find this particular project to be useless. I can't imagine why I ever would want to do this. But: they make it clear that it was a community effort, and even singled out the non-Apple-employee who did the legwork to make it happen.

At the end of the announcement, they reiterated that the source code and process are both open, and provided links to the Swift forums and issue tracker, and called for more people to get involved.

I agree that Apple doesn't seem to be improving Swift in the ways I want it improved, but this is not a good example of that. This is the story of someone (not at Apple or Amazon) who saw something they wanted to do (use Apple's tools with Amazon's services), and made it happen. Good for Fabian! I'm not going to criticize Apple for offering some help and writing a blog post about it.

None of the other languages I use---C++, Python, Go, Rust--come with a first-party cross-platform GUI library...

Python has first-party support for tcl/tk


C++ does come with OS vendor specific GUI libraries though, which is one of the reasons why I don't bother much with Rust, although I kind of like it.

I just don’t think that’s where Apple’s priorities are for swift. They want a modern language for their platform first and foremost, and then secondly if they developers can write server components for their apps in Swift, then that’s good as well.

I wonder if they're hoping people that choose Swift as their first programming language will experience "vendor lock-in" and will be disinclined from branching out to other platforms that don't support Swift. This would make sense given the Swift Playgrounds initiative.

Microsoft ignored the same exact point (official multiple UI) for C# for years, despite having it at some point (Silverlight out of browser). So I can totally understand what you are expressing there, yet I think there are even less chance Apple act on and provide such framework in the future.

I am quite on your side, except for one thing : i don’t really care about UI code anymore, because i think those have to be done using native components and framework for better OS integration and performance.

what i would LOVE however is a way to share business logic code and network code coded in swift between ios and android easily. I believe it should be straightforward using android ndk and clang, but for some reason i have never seen someone successfully implement it.

And of course, being able to call this same code from an electron app on windows would be a great thing..

> I truly love Swift, like god-damn is it my cup of tea

I also feel similarily strongly about the language itself, I find myself really productive in it. But for the kind of work I do I do need more portability that what it currently offers. I have my eye on Rust but it looks just a little too low level for what I want, general purpose-do everything language, focus on saftey, reasonable performance.

If you have tons of Swift code that needs to run in watchOS, iOS, iPadOS AND the cloud, this would kinda make sense... but how frequently is that the case? When I was still doing mobile the goal was to write as LITTLE client-side code as possible and put as much logic/heavy lifting on the API side as possible because we can make changes there far quicker than in the native client. And almost all of the client-side code was about GET/POSTing to the API or interacting with the SDK to draw things on the screen -- almost no business logic. That said, I didn't work much on apps that were supposed to work without a data connection for long periods of time... in that case it's more likely you'll run into scenarios where you're writing business logic in the app (in Swift/ObjC) but even then the goal was to keep that kind of code to a minimum (or less).

Swift is a nice language in its own right, and, according to the post, is a good fit for the lambda environments.

So there doesn’t need to be a direct connection to iOS to decide to use Swift for serverless function. A developer might just decide to use Swift for serverless functions.

(I can see the benefit to sharing certain kinds of code between client and server, but a lot of things have to line of for this to make sense, so I’m not sure if that’s a significant driver.)

Swift does not allow null pointer, and therefore there is no null pointer exception. This is a very nice feature, especially compared with other server-side compiled languages like Golang and Java. Swift is modern and concise, I hope it takes off on server-side.

Well you can always force unwrap and shoot yourself in the foot

Ah foot guns. I miss them so.

But really, I've been struggling learning swift... I became the iOS developer with little to no experience.

Apple’s goal for Swift is to be "the new default language for computer science." They see it as supplanting Java.

Whether you think that's crazy or not, pure server Swift is a thing, personally I love it. https://vapor.codes

Apple's goal for Swift is quite clear on its documentation, to replace C and Objective-C. As for anything else it isn't quite clear.

> The goal of the Swift project is to create the best available language for uses ranging from systems programming, to mobile and desktop apps, scaling up to cloud services. https://swift.org/about/

> "My goal for Swift has always been, and still is, total world domination," Chris Lattner, the creator of Swift, said onstage at Apple's Worldwide Developers Conference in 2017. https://www.businessinsider.com/developers-love-swift-apple-...

I'm having trouble finding the specific bit about "default language for computer science," might have been his interview on the ATP podcast. anyway

What Chris Lattner might desire and what Apple wants isn't the same thing, specially since nowadays he doesn't get much to say on where Swift goes.

Had he stayed at Apple overseeing the language design I would agree.

Java? Where I am, the language of computer science is, and has been for the last 5 years or so, Python. I rarely see Java outside enterprise applications anymore (and Android, though it's being supplanted by Kotlin there). Java is the new COBOL.

Java is the default language for computer science??

At many universities it's the language they teach and have most of their exercises in. The exercises that are explicitly about something else excluded. Functional programming -> Haskell, logic oriented programming -> Prolog, statistics -> R, writing compilers -> C with flex/yacc/bison etc. Everything else: Java. At least it was like that for me when I studied in the '00s and '10s in Vienna.

I can think of a few scenarios off of the top of my head:

App sends an event, Lambda sorts it into queue(s) for processing

App wants to know if its data is stale, asks Lambda

I think there is a niche for small, quick processing. Why write it in Node or whatever if your devs already know Swift?

Interesting, AWS Lambda provides a runtime API so you can implement your own runtimes. kewl https://docs.aws.amazon.com/lambda/latest/dg/runtimes-api.ht...

Always happy to see more new Swift projects pop up, especially on the server side. It's great watching the language evolve and continue to add more powerful features.

This is a great and very useful addition to the Swift ecosystem.

Currently develop a very popular iOS/macOS app in Swift which talks to an AWS Lambda backend written in Node.js. This has required some model code to have dual Swift and Node versions. If the Swift AWS Lambda Runtime was available previously this wouldn't be necessary.

I'd say a lot of developers in the Apple eco-system would be in a similar situation and this runtime can help to streamline a lot of client-server approaches.

That’s great news. For some reason cloud function run extremely slowly for me on Firebase. Like a few seconds slow on the first call if not called frequently, then it drops to milliseconds level.

That's by design. Your server 'sleeps' and

- wakes up on for a request(few seconds delay on request),

- stays awake (requests are fast here),

- goes back to sleeping if idle for sometime (15mins?)

This is what keeps the costs low (or free). Same is true for Heroku, Lambda, Vercel, Azure Functions, etc.

Sure but it is not an acceptable level of latency when the product is supposed to respond on user input. When the app or the feature is new or obscure it would fall in this state all the time.

Last time I checked I wasn’t renting a server, it was supposed to be a service that’s fast at any scale.

A 5$ DO instance would provide much better experience. They should give an option to keep it awake albeit at a cost.

Cloud functions are not a good option for low traffic services where you'd like to have good latency.

Cloudflare Workers are probably the best option in terms of cold starts and latency but are much more limited than other services.

To reduce cold-start latency in AWS Lambda, use "Provisioned Concurrency": https://aws.amazon.com/blogs/aws/new-provisioned-concurrency...

The easiest way around it is to keep ping-ing it every 5 mins from either from a third party (like pingdom, uptimerobot.com) or a cron function (https://cloud.google.com/scheduler/docs/creating).

But I would recommend using Cloud Run instead.

Pinging a Lambda is the blind leading the blind. Your Lambda still gets periodically shut down and you still have cold starts! To avoid cold start, don’t use Lambda!

Isn't Cloud Run's cold start latency even worse?

Actually you are right. I was under the impression that we can define minimum-maximum instances to run. But apparently it scales down to zero and there is no way to prevent that.

Azure functions has that option, but at some point... Why not just use a "real" web server if you want it always online? The whole point of serverless was that you don't need a server always running in the background.

Lambda also provides this functionality — they call it "provisioned concurrency": https://docs.aws.amazon.com/lambda/latest/dg/configuration-c...

I don’t want to deal with it until it’s worth dealing with it. That is, until the cost of managing a server and it’s integration is less than the cost of using Firebase(which comes with free integration and no management needs).

Yes, but I usually run my lambda function in multiple regions

This gives user low latency if the service is being used

If I've to launch DO server in 10 region, it will cost me $50 even if I am receiving a few request per day.

Yeah, this is called a 'startup effect' in most cloud function environments. Lambda has a thing called 'prewarming' which basically hits it every 15ish seconds to make sure it's still active...

Lambda has provisioned capacity now. You can just tell it how many to keep warm and it'll keep that many warm (but still cold start additionally as necessary).

I am considering to implement something like that by myself. It’s not an acceptable performance otherwise. Alternatively I am looking into running it on different tech, I would have moved already on Swift on Linux if Fireplace had a library for Swift beyond iOS.

Does it really sleep in 15 seconds such that it needs to warm up? Why call it every 15 seconds? Why not every hour, every day? Is there a documentation how often it needs a warm-up?

I believe AWS docs say that your function is loaded on a machine for 15 seconds after termination... so if a new request comes in during that time it goes to that function instead of starting a new one.

This is cool --finished a deep dive of SwiftNIO all the way down to the IETF "TAPS" specification (ah, good 'ole Courier font, brings a tear to my eye).

Will my soul brother, the great chrome dome Werner Vogels, be joining the flamboyant users of the most advanced hair care products ever invented on stage this year during WWDC to announce new support of Apple? macOS instances that can be spun up and down from Screen\ Sharing.app? Xcode compile farms that work seamlessly with a new iPad Pro edition of Xcode? Apple-subsidized (so free) access to all AWS for developers? (oh, I can dream)

If not, then there's nooo way I would use Swift outside of The "ecosystem" (first time I've read that expression used inside of Apple's own documentation, albeit on a GitHub project), though I might use SwiftNIO back ported to iOS to do something cool with Multipeer and ARKit.

swift is a nice language. however, don't do the mistake of developing server side applications on it. tried it, after drinking the ibm, vapor kool-aid in 2016ish. the community though friendly is weak. still to well known stacks if you're going to be doing server side stuff

Given lambda can only possibly send one request at a time to a handler, what is the advantage of using the non-blocking primitives and separate worker thread versus doing work on the main thread?

In this model, the only advantage would be parallelism inside the request. If you had to fetch 100 things as part of this request there’s no need to do them one by one.

Anyone used compiled languages with cloud functions?

I've only used JavaScript but I'm guessing a compiled binary (eg: Go) would have better cold starts, no?

Last time I herd c# had best cloudstart performance on lambda.

All of the closure obsession in Swift is extremely off-putting to me.

Upvoted. The recent UIKit APIs with all sorts of “configurator” and “provider” closures are very bad (e.g. check out the UIContextMenu APIs for a good cringe). You don’t know if something is sync or async, called once or multiple times, which thread is it called on, etc. I don’t think they constitute good API design, especially since we’re talking about a reference-counted environment, where capture semantics are of utmost importance...

Can you elaborate?

Closures everywhere... why? They make code difficult to reason about and read and only seem to satisfy the FP zealots.

You don't have to be a functional programming zealot to be able to recognize the value of not having to define a function just so you can sort a list using a different predicate.

Except that’s not the extent of how programming with closures is forced on Swift coders.

Essential all major modern languages have collection sorting functions built into the base collection types that accept “by” (or similar) arguments... which is quite intuitive to even Jr. programmers.

OK, what's an actual example of your problem? I don't write Swift, but I'm curious about it - where's a closure used when some fixed logic would've sufficed?

Did you read the parent article? Good examples there.

You can only get around callbacks for async IO with async/await or language-integrated N:M threading, which is a challenging problem (I still trigger ICEs in Rust's implementation on occasion). Java is another language which suffers from this, and C++ only got coroutines in C++20.

I don’t see anything in the example to indicate that the closure pattern for Swift Lambda handlers actually allows true async.

func lambdaHandler(event: Event, context: Context) { // your lambda handler logic... }

What’s wrong with this approach, which is how lambda handlers are written in every other language with the exception of JavaScript - let’s not pretend that JavaScript is a good language design reference.

Look at this Go example In comparison... simple, readable, intuitive:

package main

import ( "fmt" "context" "github.com/aws/aws-lambda-go/lambda" )

type MyEvent struct { Name string `json:"name"` }

func HandleRequest(ctx context.Context, name MyEvent) (string, error) { return fmt.Sprintf("Hello %s!", name.Name ), nil }

func main() { lambda.Start(HandleRequest) }

Here's an example from the official Go documentation on using closures in the same sort of place - https://golang.org/pkg/net/http/#example_ServeMux_Handle

Yes, closures are present in many languages, but they are pervasive and unavoidable in Swift. You’re avoiding addressing the idea that closures actually cause layers of (often unnecessary) indirection, make code more difficult to reason about, and make code harder to read - especially for jr. devs.

No, I'm suggesting that you've not shown they must be used any more than in other languages - and obviously in order to make sense of the examples in Go's documentation you've got to know how they work, and Go is pretty much the language designed for junior backend devs.

What worries me is not so much the somewhat excessive use of closures itself but rather the combination of closures and the potential for circulcar references.


I mean, you can do that in Swift too. You can also use closures in Go in exactly the same way, which is what I tend to do for very small functions that don't need a name.

Functions and closures-that-don't-reference-their-environment are exactly equivalent in both languages, from a quick look? It's your choice as a developer which to use.

This particular pattern in the case of Lambda is specifically for providing a closure which is called later and repeatedly - it's not waiting for a request and then calling the closure once and then returning.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact