惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
人人都是产品经理
人人都是产品经理
Cisco Talos Blog
Cisco Talos Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
V
V2EX
博客园 - 三生石上(FineUI控件)
Martin Fowler
Martin Fowler
WordPress大学
WordPress大学
D
Docker
S
SegmentFault 最新的问题
博客园 - 聂微东
美团技术团队
Apple Machine Learning Research
Apple Machine Learning Research
月光博客
月光博客
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Last Week in AI
Last Week in AI
M
MIT News - Artificial intelligence
F
Fortinet All Blogs
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
The GitHub Blog
The GitHub Blog
GbyAI
GbyAI
L
LangChain Blog
Vercel News
Vercel News
博客园 - 叶小钗
MongoDB | Blog
MongoDB | Blog
Stack Overflow Blog
Stack Overflow Blog
H
Help Net Security
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
The Cloudflare Blog
Engineering at Meta
Engineering at Meta
T
Threat Research - Cisco Blogs
T
Threatpost
Scott Helme
Scott Helme
T
Tailwind CSS Blog
Latest news
Latest news
Stack Overflow Blog
Stack Overflow Blog
Blog — PlanetScale
Blog — PlanetScale
The Register - Security
The Register - Security
罗磊的独立博客
P
Proofpoint News Feed
腾讯CDC
S
Schneier on Security
雷峰网
雷峰网
A
About on SuperTechFans
T
Tenable Blog
F
Full Disclosure
Cyberwarzone
Cyberwarzone
博客园_首页
有赞技术团队
有赞技术团队
K
Kaspersky official blog

Hacker News

OpenRouter Raises $113M Series B | OpenRouter Microcode inside the Intel 8087 floating-point chip: register exchange Ask HN: What Is the State of App Development in 2026? A Probabilistic Algorithm for Repairing All Roads in Lebanon via Papal Visits Voxel Space Memory decline after menopause linked to loss of estrogen production in brain tissue voyagecoat.com Anthropic surpasses OpenAI to become world’s most valuable AI startup AMD Customer Community Helios. Is plug-in solar worth it? Openrsync: An implementation of rsync, by the OpenBSD team pandoc-templates.org 'Mind-blowing': Iron-rich immune cells help homing pigeons navigate Danish pension fund excludes SpaceX citing governance and valuation Company accidentally blows $500M on Claude AI in one month OpenRCT2 v0.5.1 “Swamp Castle" released! Perry — TypeScript → Native What Is a Dickover? The Office of Management and Budget tries again to cripple US science MCP is dead | Quandri Engineering FreeCal — calendars for your organisation Free full BGP feed. IPv4 and IPv6 Trillion Characters The Last Technical Interview The California State Assembly Has Passed the 'Protect Our Games Act' GitHub - jmaczan/tiny-vllm: Build your own high performance LLM inference engine in C++ and CUDA - a smaller version of vLLM I Tested Whether AI Can Fix Security Vulnerabilities. Well, It's Complicated. On Rendering Diffs EV Stupidity Checklist Current Rothko AI will be used to estimate age of asylum seekers from next year SQLite is All You Need for Durable Workflows - Blog Records show UC sharing data with US Customs and Border Protection Rsync maintainer starts uses Claude, regressions mount TV Explorer — 10,000 Free TV Channels Notes from the Mistral AI Now Summit in Paris GTA 6 Developers Unionize bijou64 It Will Never Be the Year of the Linux Desktop · unix.foo I Am Retiring from Tech to Live Offline Blue Origin rocket explodes on launchpad in a setback Headway Therapy Patients Forced to Scan Their Faces to Keep Getting Care It's hard to justify buying a Framework 12 Please Use AI Expertise in the Age of AI Poisonous invasion: What is the 'devil's trumpet' harming crops in Iraq? Step 3.7 Flash — A high-efficiency Flash model for Real-World Canada slipped into a technical recession on an annualized basis as economic growth stalled in 1st quarter local git remotes — alexander cobleigh Poll: How often do you check "newest"? We should be more tired than the model High Density Living, 2000 Years Ago: Inside the Roman Apartment Building Danish Pension Fund Blacklists SpaceX, Citing Governance Issues Free Furigana Converter: Kanji to Hiragana | EZFurigana The UK Government's Low Value Purchase System is a Waste of Time We should be more tired than the model Forward Deployed Engineer: AI + HPC at Cedana | Y Combinator Testing the WWI concrete ships and WWII concrete barges Hundreds of prolific Wikipedia editors are threatening to go on strike This AI startup will clean your home for free to train future robots Tulip mania: when a single flower was worth more than a house Is AI causing a repeat of Frontend’s Lost Decade? Digital Identity Management in Norway is a Success but also a Disaster - Research News Jamie Hurst's Blog - Is this sustainable? Real-time LLM Inference on Standard Datacenter GPUs (3,000 tokens/s per request) wterm | Terminal Emulator for the Web Corporate America Is Starting to Ration AI as Cost Skyrockets GitHub - office233/Nexuscortex: Experimental sparse cognitive architecture written in Go. SDR attention, ternary compute, memory systems, sleep consolidation, 137 tests. US Military personnel are being targeted using location data zot. Yet another coding agent harness. [BUG] Login no more possible, Android App still works GitHub - RasmusGodske/claude-hook-utils GitHub - HeidiSQL/HeidiSQL: A lightweight client for managing MariaDB, MySQL, SQL Server, PostgreSQL, SQLite, Interbase and Firebird, written in Delphi and Lazarus/FreePascal Let's compile Quake like it's 1997! Cars are trying to spy on you, and it's only just the beginning Strengthening societal resilience with Rosalind Biodefense Italians and Dutch share the same gestural instinct for teaching The most spectacular rocket explosion since N1 just happened in Florida I Read the Claude Code Source Code. Here's Everything You Can Configure That the Docs Don't Tell You. The Secret Garden of Rock-Paper-Scissors Blue Origin's New Glenn blows up during static fire test Microsoft data suggests using AI is more expensive than hiring people Where Are the Economies of Scale in Homebuilding? ‘We cannot ban our way out of a youth mental health crisis’: social media bans for teenagers lack evidence and pose risks, scientists say - Science news Someone used my open source project to phish 14,000 people AI Job Grief: The Unnamed Psychological Crisis Hitting Tech Workers Ember 7.0 Released The DLES.gg Manifesto Vibe Coding Is Not Engineering Bot Company allegedly trashing Airbnb rentals with their prototype robots I'm "Retiring" from Tech – Chad Whitacre, Head of Open Source, Sentry.io Ask HN: Entrepreneurs, how long did it take you to succeed? US troops are reportedly being targeted using location data, Pentagon says Fed up with vibe coders, dev sneaks data-nuking prompt injection into their code I Made a Million Dollar Product from My Dorm Room - Nick Winans Disgruntled 0-day hunter 'humiliated' by Microsoft pledges 'bone shattering drop' as Redmond calls cops White House proposes new rules giving political appointees final approval on research grants Bricks and Minifigs Stole a Man's $200k Lego Collection Separate The Cord From The Device Client Challenge
Stateless Actors
Matt Massicotte · 2026-05-29 · via Hacker News

May 29, 2026

Recently, I was asked an interesting question. If the purpose of an actor is to protect mutable state, is a stateless actor pointless?

At first, I thought it was an easy answer. Actors exist to define a little, protective bubble around state. They "isolate" data away from any unsafe accesses. An actor that has nothing to isolate seems like a strange thing.

Can such an arrangement serve a purpose?

Note

I wrote another thing on actors that might be interesting.

Easy non-MainActor types

A thing I run into from time to time is a "NetworkClient"-style type. It contains methods that deal with some network API. It isn't uncommon for these kinds of types to be actors.

actor NetworkClient {
	func loadCart() async throws -> [Product] {
		let (data, _) = try await URLSession.shared.data(for: cartRequest)

		return try JSONDecoder().decode([Product].self, from: data)
	}
}

This particular NetworkClient is an actor that has no state. But it being an actor gives it two advantages. First, actor types are Sendable. That means we can pass this type around easily without having to think very much.

And second, this loadCart method will never run on the main thread. Default actor types execute their synchronous work on a shared thread pool. The JSON decoding here could be expensive. Ensuring that work does not ever happen on the main thread is nice.

I'm reaching a little, but a believable third reason is this type might just not have state yet. We might end up with caches or authentication, and all that will need a place to live.

(It has been pointed out that predicting ahead of time where state could live can itself be problematic. I tend to agree so be extra careful here.)

I think this is fine provided you are doing all this intentionally. As long as you understand the trade-offs, go for it. But there really are trade-offs here. Most notably, actor types can be difficult/impossible to use with protocols. And, they also require both their method inputs and outputs to be safe to transfer into/out of the actor. They push you towards needing more Sendable types.

Now, contrast with this:

struct NetworkClient: Sendable {
	@concurrent
	func loadCart() async throws -> [Product] {
		let (data, _) = try await URLSession.shared.data(for: cartRequest)

		return try JSONDecoder().decode([Product].self, from: data)
	}
}

This type has some advantages. The first is it can be easier to use with protocols because you won't have to wrestle with isolation mismatches.

The second problem is an artificial limitation. Actors run synchronous blocks of code serially. This means no matter how many tasks you throw at this NetworkClient actor, it will only be able to decode JSON responses one at a time. With a @concurrent function, we no longer have that limitation.

I'm definitely not saying that a struct is better here. But there are serious trade-offs and they are worth thinking about.

Note

Check out this post for more information on how to manage expensive work.

The background actor

Here's an interesting type!

@globalActor
actor BackgroundActor {
	static let shared = BackgroundActor()
}

And then, you can use it in all places where a global actor annotation works.

Task { @BackgroundActor in
	// definitely not @MainActor anymore
}

I get it. We're used to seeing the one global @MainActor. This gives us a familiar way to define non-main work. But such a type has two serious drawbacks.

Just like with our NetworkClient actor above, this BackgroundActor executes synchronous work serially. It cannot run more than one background task at time. That's not an ideal quality for a tool like this.

Another problem is that global actors integrate very tightly with the type system. When you add one, you are forcing the compiler to guarantee the work is executed on that actor. This can have a viral effect, something many people notice with MainActor. And the reverse can also be true. If you later change your mind, removing a global actor can also be painful.

I'm sympathetic to the motivations here. But I really think you'll be best served by taking some time to learn about the language's existing constructs for controlling isolation. I'm not sure that's really optional anyways, so it feels like a good investment.

Custom executor actors

I somehow forgot about this one, but thankfully Gwendal did not let me get away with it!

It's not something you'll need everyday, but actors that exist purely to adapt Swift's concurrency system with another, preexisting system are very important. This is one of the primary use cases for custom executors.

This is a powerful tool and is surprisingly easy to use with a dispatch queue. I've seen this used to better integrate with AVFoundation. But the approach can potentially work with any other queue-based system.

If you'll allow me to lift an example from the migration guide:

actor LandingSite {
	private let queue = DispatchSerialQueue(label: "something")


	nonisolated var unownedExecutor: UnownedSerialExecutor {
			queue.asUnownedSerialExecutor()
	}


	func acceptTransport(_ transport: PersonalTransportation) {
		// this function will be running on queue
	}
}

Another example of this, and one that I'm pretty embarrassed I didn't think of, is the MainActor! This actor doesn't have any direct properties, but it most certainly does manage state - the entirely of the UI. So it kind of straddles the line here, but it's still very interesting to consider.

The file system

Ok, this is an interesting one. The file system is absolutely a form of state. But it is state that is outside of our program and completely invisible to the compiler. This is a case where I think a "stateless" actor can make sense. The state does not have to literally mean instance properties.

Say you have some kind of on-disk cache, used by lots of different parts of your system. Concurrent accesses could corrupt the files/directories involved. The serialization an actor provides gives you a way to prevent that. It isn't ideal, because the compiler cannot check your work. And getting it right does require manually encapsulating everything, but you probably want to do that anyways.

One concern that can come up here is blocking operations. When you read/write to the disk, you're doing it synchronously. That means this actor is tying up one of the concurrency runtime's threads. Those are a finite resource, and on the order of the number of CPU cores per priority level. This is quite different from GCD, which will happily create a large (but still ultimately finite) number of threads if none are available.

My opinion is that you usually do not need to concern yourself with this. Sure, a thread is occupied. But what specifically it is occupied doing is typically not an important detail. As long as the work satisfies the runtime's requirement of forward progress, you should be fine.

However if you are worried (or know for a fact) you will not be fine, shifting your blocking work off the concurrency pool's threads makes sense and is usually quite easy to do. GCD is still here and you should not be afraid to use it.

(I forgot that Jaim also wrote about this, and went into quite a bit more detail. Worth checking out.)

The first rule of actors

Actors have a tendency to be over-used. They are a very useful tool, and I prefer them to locks or queues. But like any synchronization primitive, you should be able to clearly articulate why it is necessary. This is the first rule of actors.

I think that in general, yes. An actor with no state is a strange thing. It could represent a misunderstanding. It might be making a design more complex. But I think they definitely can also make sense.

Did you know that I do consulting for concurrency and Swift 6 migrations? If you think I could help, get in touch.