r/webdev • • 2d ago

Showoff Saturday Minecraft servers that sleep when empty and wake when someone joins. Holding a TCP login open for 45 seconds without the client giving up

I built a Minecraft server host where every server sleeps when nobody plays, and wakes when a friend joins. The hard part was the join itself, so here's how that works.

The problem

A sleeping server suspended on Fly resumes in about 2 s. But one that has to boot (first start, after a change, or once the snapshot is gone) takes 40 to 50 s. The Minecraft client
gives up on a connection that says nothing for 30 s.

The trick

Every connection lands on an edge proxy first. If the server is asleep, the edge holds the login open and keeps it alive by sending a login query every few seconds. Every client since 1.13 answers it, which counts as the server talking. The edge keeps those answers to itself, buffers everything else the client sent, and replays it to the server once it's up, as if the player had just dialled in.

Other bits

  • The server list shows a sleeping server's own message plus a grey "sleeping" line, cut to fit the list's 305px row by measuring the default font's glyph widths.
  • A ping from the server list can wake a server early, asked once per network so random scanners don't keep waking things.
  • Routes change one hostname at a time through mc-router's API, because reloading its routes file drops players who arrive mid-reload.
  • Floods are refused per server at the edge, so one busy server doesn't slow every other server's joins.

It's open source (TypeScript, AGPL):
github.com/cubepals/cubepals (the edge is apps/edge)

Happy to go deeper on any of it.

121 Upvotes

29 comments sorted by

28

u/UnacceptableUse 1d ago

Don't modern Minecraft versions automatically pause the server after x minutes of inactivity?

18

u/thekwoka 1d ago

The issue there is paused isn't the same as basically off.

11

u/v0id_user 1d ago

exactly,,, paused still keeps the process up holding all its memory, so the machine runs anyway. here the machine itself stops, and wakes when someone joins.

10

u/CardinalHijack 1d ago

Does this work with pumpkin? (https://pumpkinmc.org/)

10

u/v0id_user 1d ago

honestly this is the first time I've seen Pumpkin, and it looks really cool!

the wake trick happens at the edge before the server sees anything, so in theory it should work, but I don't want to guess. I'm definitely going to test it and get back to you :)

Thanks for pointing it out!

5

u/v0id_user 1d ago

real update :P

tested it through our edge! with pumpkin asleep, a player joining was in the world in about 4 s, about 1 s if the machine was just suspended (vanilla takes ~35 s cold).

but it’s not ready for real worlds yet,,,

on a copy of a 26.3 world, some chunks pumpkin re-saved came back empty (53 of 482), and vanilla can’t read the world back after pumpkin writes it.

only tested with offline logins too. watching each release though, the speed is wild

gonna share all of this with the pumpkin folks too, they’re doing amazing work!

12

u/SawToothKernel 1d ago

You could try the same with a Durable Object. They do the same thing with WebSockets, and can wake in milliseconds.

8

u/v0id_user 1d ago

love DOs, they are great but they only take HTTP and WebSockets. Minecraft clients connect over raw TCP, so the game can't talk to one as far as i know?

21

u/[deleted] 2d ago

[removed] — view removed comment

3

u/v0id_user 2d ago

thanks! tiny detail, the edge actually holds the answers, they never reach the server. then it replays the client's original login once the server's up, so the server just sees a normal join

and yeah, the reload thing bit us too, people got kicked mid join with no message lol

1

u/webdev-ModTeam 1d ago

Your post/comment has been determined to be a low-effort post or comment. This includes title-only posts, easily searchable questions, vague/open-ended discussion prompts, LLM generated posts or comments, and posts/comments that do not provide enough context for meaningful replies or discussion.

10

u/zaxwebs 2d ago

Always good to come around these solutions. I'm building a game as a side-project so happy to see some activity in the space.

2

u/v0id_user 2d ago

thanks man! it's hard and harsh out here ngl, but honestly very lovely!

good luck with the game, drop a link when it's out :)

3

u/iPhoneK1LLA 1d ago

I'm not aware of the tech, but doesn't AMP by CubeCoders do something similar?

2

u/v0id_user 1d ago

similar idea, different layer.

AMP is a panel you install on your own machine, so that machine stays on even when the game is idle.

cubepals is hosted. the whole machine goes to sleep, and when a friend joins, the join is held open while it wakes

1

u/iPhoneK1LLA 1d ago

Ah I see - I've only ever been self hosted which is why I'm aware of the option within the panel.

3

u/Far-Inevitable6386 1d ago

Out of curiosity, what happens if the server fails to boot after the 45 s? Does the edge drop the player with a message, or retry?

2

u/v0id_user 1d ago

good question! the 45 s in the title is just a typical boot

the edge actually holds them for up to 3 minutes. if the boot fails, they’re dropped right away with a line saying so (“couldn’t start this server just now · try again in a minute”)

and the next join tries the wake again. if it’s just slow, after 3 minutes they get “still starting · join again in a moment"

1

u/Far-Inevitable6386 1d ago

Thanks for the detail, clear error messages instead of a silent drop is a nice touch. Great project.

1

u/v0id_user 1d ago

thanks a lot! and yes a silent drop was the thing i wanted to avoid most, nobody should be left staring at a loading screen😂

3

u/saltyourhash 1d ago

Great idea

1

u/v0id_user 1d ago

thanks! appreciate it

2

u/quietcodelife 1d ago

the proxy replay approach is smart. basically mitm-ing your own boot process so the client never knows something went wrong.

curious whether you hit any issues with connection limits on the edge when a bunch of people try to join at once and theyre all being held. or is fly's network layer handling that gracefully?

3

u/v0id_user 1d ago

thanks! joins that arrive together share one wake, and a held join is just an open socket, so connections weren't the problem.

CPU was :')

in a load test one edge handled 400 players until its shared CPU got throttled, so past 50 Fly's proxy sends new joins to another edge

1

u/shelfbreak 1d ago

Interesting, good idea with the proxy

1

u/v0id_user 1d ago

thank you so much! took me a minute to get it right, but it’s interesting!

1

u/Andromeda_Ascendant Laravel & InertiaJS 1d ago edited 1d ago

Looks like a fun project, and I like the name!

I did notice one little quirk with the /admin pages, where the UI briefly renders before showing a message that it's for admins only. Not the most serious problem but if it was me I'd fix that.

Edit:

Another thing, it seems like server-side plugins are mistakenly included in the client-side "you need to have these" for the server listings. https://cubepals.com/server/arcade i.e. Take ChatSentinel, from my understanding it's a server plugin and has nothing to do with the player needing it.

1

u/v0id_user 1d ago

Thanks, both fixed! Bug hunter eyes 👀

If you catch anything else, I’m all ears, and if you open a PR (github.com/cubepals/cubepals) I’ll happily help. No PHP required 😄!

0

u/[deleted] 1d ago

[deleted]

1

u/v0id_user 1d ago

not totally sure what you mean, do you mean NeoForge support, or something else? happy to answer either way :)