[{"data":1,"prerenderedAt":77},["ShallowReactive",2],{"api:\u002Fapi\u002Fconfig:en":3,"api:\u002Fapi\u002Fnotes:en":8,"api:\u002Fapi\u002Fprojects\u002Fbooking-slots:en":32},{"email":4,"lang":5,"name":6,"role":7},"hello@ewsirdev.example","en","Ewsirdev","Web developer: websites, landing pages and Go services",[9,16,22,27],{"slug":10,"lang":5,"title":11,"date":12,"summary":13,"project":14,"minutes":15},"double-booking","Double booking: a transaction plus a partial UNIQUE index","2026-10-20","How booking-slots protects against two clients booking the same time at once, and how that protection is tested.","booking-slots",1,{"slug":17,"lang":5,"title":18,"date":12,"summary":19,"project":20,"minutes":21},"lease-and-fencing","Lease and fencing: how a queue neither loses a job nor lets a zombie finish it twice","A worker can crash, stall, or wake up after its job was taken by someone else. How the lease and the lease token in job-queue deal with that on SQLite.","job-queue",2,{"slug":23,"lang":5,"title":24,"date":12,"summary":25,"project":26,"minutes":21},"p95-nearest-rank","p95 in an uptime monitor: the nearest-rank method and what it does not hide","How uptime-monitor computes p50\u002Fp95 latency and uptime, why the nearest-rank method was chosen, and where those numbers can mislead.","uptime-monitor",{"slug":28,"lang":5,"title":29,"date":12,"summary":30,"project":31,"minutes":21},"websocket-from-scratch","WebSocket on the standard library: what really happens under new WebSocket()","Why realtime-rooms has its own RFC 6455 layer, which protocol violations it checks, and why a library is still the better choice for production.","realtime-rooms",{"slug":14,"title":33,"type":34,"stack":35,"description":39,"highlights":40,"run":45,"hue":46,"og":47,"shots":48,"case":56,"case_lang":5,"prev":71,"next":74},"Appointment booking","backend",[36,37,38],"Go","SQLite","Docker","Online booking: free slots computed from service duration and working hours, double-booking protection, an admin panel. A fictional studio, demo.",[41,42,43,44],"Free slot calculation","No double bookings","Admin for services and schedule","Tests and Docker","cd booking-slots && go run .",65,"\u002Fog\u002Fen\u002Fbooking-slots.jpg",{"desktop":49,"desktop_sm":50,"mobile":51,"dw":52,"dh":53,"mw":54,"mh":55},"\u002Fshots\u002Fbooking-slots-desktop.webp","\u002Fshots\u002Fbooking-slots-desktop-sm.webp","\u002Fshots\u002Fbooking-slots-mobile.webp",1280,800,390,844,{"about":57,"features":60,"run":65,"notes":69},[58,59],"Online booking for a fictional studio: the client picks a service, a day within the next two weeks and a free time, and leaves contact details. The owner manages everything in the admin panel.","Slots are computed from the service duration, the working hours of the weekday and the intervals already taken. Double booking is ruled out by a transaction and a unique index.",[61,62,63,64,44],"Free slot calculation on a 30-minute grid","Overlap check in a transaction plus a partial UNIQUE index in SQLite","Admin panel: bookings, services, working hours, closed dates","Time zone from an environment variable; tzdata embedded in the binary",[66,67,68],"git clone \u003Crepository on request> booking-slots","cd booking-slots","go run .   # http:\u002F\u002Flocalhost:8083, admin panel at \u002Fadmin",[70],"The studio, services and prices are fictional. The admin token comes from ADMIN_TOKEN; if it is not set, one is generated and printed to the log.",{"slug":72,"title":73},"link-shortener","Short: link shortener",{"slug":75,"title":76},"landing-studio","Halftone: lighting studio",1792697892725]