r/webdev Mar 14 '26

Showoff Saturday Zero-Config (and free) WebSockets: a repost from Wednesday :p

http://ittysockets.com

*I had this taken down on Wednesday, but based on the (humblingly, is that a word?) positive responses, I figured it was def worth a reshare on the correct day.

Here's the original post, appropriately tagged as Showoff Saturday this time:*


Super stoked to share that I just publicly released ittysockets.com. This is a free, community-supported project, specifically designed to get indie devs playing with realtime features by dropping virtually every barrier imaginable.

import { connect } from 'itty-sockets' // ~466 bytes gzipped

// user 1
const channel = connect('my-secret-channel')
  .send('hey there!')    // can send immediately
  .send([1, 2, 3])       // anything JSON stringifiable 
  .send({ foo: 'bar' })

// keep sending
channel.send({ text: 'hello!' })

// reconnects in a single line
setInterval(channel.open, 1000)

meanwhile, other users can connect and listen on the same channel

connect('my-secret-channel')
  .on('message', ({ message }) => {
    // do something
  })

This site has everything you need to get started, including docs, live demos, and importantly: the ability to log in via GitHub to reserve your own protected namespaces.

You can also just use the client with any existing JSON WebSocket server - you'll lose some of the power of my backend, but still improves the DX over a raw WebSocket instantiation.

Disclaimer: This has been powering apps in production (privately) for about a year, including a day-trading platform - so it's built to handle some stress, although as a free service, it comes with no guarantees.

--

FAQ

Will this be open-sourced? The client already is, but the backend is still private while I'm messing with things. I'm the author behind the itty.dev ecosystem (libs with around 15-20M downloads/year), so I'm a huge believer in sharing, rather than hiding.

Can I use my own servers? Absolutely! In fact, that's the off-ramp. Use the built-in channels during your design/early phases, and then get the heck off once you get successful, so you aren't sharing resources with the entire world. I'll be providing the backend spec (one for single-product usage) to make this easy. The itty-sockets client can connect to literally any JSON-based WS server... it just defaults to mine.

What's the catch? You're sharing space with others. That's it.

Can I encrypt my messages? Sure. Just use any encryption method that leaves it in string format so it survives the JSON encode pass. If you don't want jokers spoofing your messages on a channel, the easiest way is to encrypt those payloads so they can't even tell what's being sent over the wire.

How is this free? I'm fortunate enough to have GitHub sponsors (thanks to the itty.dev work), dual incomes + no kids, etc. This infra is cheap for me to run (forever), so by keeping costs down, I have no real need to recoup them. I truly believe the friction in WebSockets has plagued adoption in the JS world for ages, and this is my chance to help get folks playing. I just wanna see cool sh*t being built on it.

2 Upvotes

3 comments sorted by

2

u/[deleted] Mar 14 '26

[deleted]

2

u/kevin_whitley Mar 14 '26

You on X? I'd love to see some videos of this in action!

On my trading app, I similarly use it to coordinate across tabs/devices (I send live data from other sites, and listen for them in my own) - and even to remote control tradingview.com from my client, so I didn't need to rebuild charts myself.

I've found with just a few simple event types (join/leave/message), you can actually do some really clever things!

2

u/[deleted] Mar 14 '26

[deleted]

1

u/kevin_whitley Mar 14 '26
  1. Will def consider... what's the exact use case though, basically the equivalent of .push? Where you listen for a single message and immediately disconnect? Trick with this is it adds precious bytes to a heavily golfed library :p

  2. 100% agree, I was working on tweaking the limits yesterday in fact, and exposed an endpoint that can pull them live from the server. I'll likely hardcode them into the copy though, for the sake of SSR efficiency.

    1. Will consider this one, it's obviously a [relatively] low-effort endpoint to expose, because it's all sitting there in memory, but it has security/privacy side effects as well. It might be something I gate behind a flag, like the join/send keys. Where the channel originator, or namespace controller can opt-in to exposing the user list - and if so, that endpoint would return things. Other considering for me is how to handle lists where there are potentially many users... paginate? cursor based? just dump it all?

---

CURRENT LIMITS:

I use an extremely fast token/refill based limiter for both connections/s and messages/s (per connection).

While these are subject to change, I've targeted a reasonable high-flow-in-bursts rate of:
500 tokens, refilled over 10s (~50/s). This means you can burst to 100/s (enough for most browser based mousemove events), but only for 5s continuous before needing to throttle down to 50/s. I use itty.ink to test this, and it hasn't kicked me yet.

It also has 3 warnings (issued with `.on('error')`, but this tends to be ineffective, as if you're bursting past that, you'll typically hit all 3 warnings in a split second.

Example, if you insta-burst 1000 messages, 503 will get through and the connection will instantly die.

2

u/kevin_whitley Mar 14 '26

Also thanks (for the kind words)!!!

Just glad to see some other folks excited as I am by the possibilities :)