[{"data":1,"prerenderedAt":577},["ShallowReactive",2],{"blog:/blog/migrate-from-pusher-to-nolag":3},{"id":4,"title":5,"author":6,"body":7,"category":566,"date":567,"description":568,"excerpt":569,"extension":570,"meta":571,"navigation":164,"path":572,"readTime":573,"seo":574,"stem":575,"__hash__":576},"blog/blog/migrate-from-pusher-to-nolag.md","Migrate from Pusher to NoLag","Henco Burger",{"type":8,"value":9,"toc":557},"minimark",[10,14,19,22,45,49,126,130,301,305,481,492,496,503,512,516,523,527,553],[11,12,13],"p",{},"Pusher Channels popularised hosted realtime pub/sub, and a lot of apps still run on it. If you are moving to NoLag, the good news is that the mental model is almost identical: you subscribe to a channel, you bind to events, and a publisher sends data to everyone listening. This guide maps Pusher concepts onto NoLag and shows the same subscribe-and-publish flow in both.",[15,16,18],"h2",{"id":17},"why-teams-move","Why teams move",[11,20,21],{},"NoLag keeps the pub/sub foundation you already rely on and adds a few things Pusher does not focus on:",[23,24,25,33,39],"ul",{},[26,27,28,32],"li",{},[29,30,31],"strong",{},"Blueprint SDKs"," for chat, notifications, dashboards, tracking, and more, so common patterns are a few lines instead of a from-scratch build.",[26,34,35,38],{},[29,36,37],{},"A coordination layer for AI agents",": dispatch work, share state, observe decisions, and gate actions with human approval, on the same infrastructure as your app.",[26,40,41,44],{},[29,42,43],{},"Quality-of-service levels"," and presence built in.",[15,46,48],{"id":47},"concept-map","Concept map",[50,51,52,65],"table",{},[53,54,55],"thead",{},[56,57,58,62],"tr",{},[59,60,61],"th",{},"Pusher",[59,63,64],{},"NoLag",[66,67,68,77,85,98,110,118],"tbody",{},[56,69,70,74],{},[71,72,73],"td",{},"App key + cluster",[71,75,76],{},"App (a container for rooms and topics)",[56,78,79,82],{},[71,80,81],{},"Channel",[71,83,84],{},"Room + topic",[56,86,87,93],{},[71,88,89],{},[90,91,92],"code",{},"channel.bind('event', cb)",[71,94,95],{},[90,96,97],{},"room.on('topic', cb)",[56,99,100,105],{},[71,101,102],{},[90,103,104],{},"pusher.trigger('channel', 'event', data)",[71,106,107],{},[90,108,109],{},"room.emit('topic', data)",[56,111,112,115],{},[71,113,114],{},"Presence channel",[71,116,117],{},"Presence (per room)",[56,119,120,123],{},[71,121,122],{},"Private channel + auth endpoint",[71,124,125],{},"Actors, access tokens, and per-topic ACL",[15,127,129],{"id":128},"before-pusher","Before: Pusher",[131,132,137],"pre",{"className":133,"code":134,"language":135,"meta":136,"style":136},"language-js shiki shiki-themes github-light github-dark","import Pusher from 'pusher-js'\n\nconst pusher = new Pusher('APP_KEY', { cluster: 'eu' })\n\nconst channel = pusher.subscribe('chat')\nchannel.bind('message', (data) => {\n  console.log('Received:', data)\n})\n\n// On your server, using the pusher server SDK:\n// pusher.trigger('chat', 'message', { text: 'Hello!' })\n","js","",[90,138,139,159,166,201,206,230,260,277,283,288,295],{"__ignoreMap":136},[140,141,144,148,152,155],"span",{"class":142,"line":143},"line",1,[140,145,147],{"class":146},"szBVR","import",[140,149,151],{"class":150},"sVt8B"," Pusher ",[140,153,154],{"class":146},"from",[140,156,158],{"class":157},"sZZnC"," 'pusher-js'\n",[140,160,162],{"class":142,"line":161},2,[140,163,165],{"emptyLinePlaceholder":164},true,"\n",[140,167,169,172,176,179,182,186,189,192,195,198],{"class":142,"line":168},3,[140,170,171],{"class":146},"const",[140,173,175],{"class":174},"sj4cs"," pusher",[140,177,178],{"class":146}," =",[140,180,181],{"class":146}," new",[140,183,185],{"class":184},"sScJk"," Pusher",[140,187,188],{"class":150},"(",[140,190,191],{"class":157},"'APP_KEY'",[140,193,194],{"class":150},", { cluster: ",[140,196,197],{"class":157},"'eu'",[140,199,200],{"class":150}," })\n",[140,202,204],{"class":142,"line":203},4,[140,205,165],{"emptyLinePlaceholder":164},[140,207,209,211,214,216,219,222,224,227],{"class":142,"line":208},5,[140,210,171],{"class":146},[140,212,213],{"class":174}," channel",[140,215,178],{"class":146},[140,217,218],{"class":150}," pusher.",[140,220,221],{"class":184},"subscribe",[140,223,188],{"class":150},[140,225,226],{"class":157},"'chat'",[140,228,229],{"class":150},")\n",[140,231,233,236,239,241,244,247,251,254,257],{"class":142,"line":232},6,[140,234,235],{"class":150},"channel.",[140,237,238],{"class":184},"bind",[140,240,188],{"class":150},[140,242,243],{"class":157},"'message'",[140,245,246],{"class":150},", (",[140,248,250],{"class":249},"s4XuR","data",[140,252,253],{"class":150},") ",[140,255,256],{"class":146},"=>",[140,258,259],{"class":150}," {\n",[140,261,263,266,269,271,274],{"class":142,"line":262},7,[140,264,265],{"class":150},"  console.",[140,267,268],{"class":184},"log",[140,270,188],{"class":150},[140,272,273],{"class":157},"'Received:'",[140,275,276],{"class":150},", data)\n",[140,278,280],{"class":142,"line":279},8,[140,281,282],{"class":150},"})\n",[140,284,286],{"class":142,"line":285},9,[140,287,165],{"emptyLinePlaceholder":164},[140,289,291],{"class":142,"line":290},10,[140,292,294],{"class":293},"sJ8bj","// On your server, using the pusher server SDK:\n",[140,296,298],{"class":142,"line":297},11,[140,299,300],{"class":293},"// pusher.trigger('chat', 'message', { text: 'Hello!' })\n",[15,302,304],{"id":303},"after-nolag","After: NoLag",[131,306,310],{"className":307,"code":308,"language":309,"meta":136,"style":136},"language-ts shiki shiki-themes github-light github-dark","import { NoLag } from '@nolag/js-sdk'\n\nconst client = NoLag('your_access_token')\nawait client.connect()\n\nconst room = client.setApp('chat').setRoom('general')\nroom.subscribe('message')\n\nroom.on('message', (data) => {\n  console.log('Received:', data)\n})\n\n// Publish from any authorised client:\nroom.emit('message', { text: 'Hello!' })\n","ts",[90,311,312,324,328,347,361,365,396,409,413,434,446,450,455,461],{"__ignoreMap":136},[140,313,314,316,319,321],{"class":142,"line":143},[140,315,147],{"class":146},[140,317,318],{"class":150}," { NoLag } ",[140,320,154],{"class":146},[140,322,323],{"class":157}," '@nolag/js-sdk'\n",[140,325,326],{"class":142,"line":161},[140,327,165],{"emptyLinePlaceholder":164},[140,329,330,332,335,337,340,342,345],{"class":142,"line":168},[140,331,171],{"class":146},[140,333,334],{"class":174}," client",[140,336,178],{"class":146},[140,338,339],{"class":184}," NoLag",[140,341,188],{"class":150},[140,343,344],{"class":157},"'your_access_token'",[140,346,229],{"class":150},[140,348,349,352,355,358],{"class":142,"line":203},[140,350,351],{"class":146},"await",[140,353,354],{"class":150}," client.",[140,356,357],{"class":184},"connect",[140,359,360],{"class":150},"()\n",[140,362,363],{"class":142,"line":208},[140,364,165],{"emptyLinePlaceholder":164},[140,366,367,369,372,374,376,379,381,383,386,389,391,394],{"class":142,"line":232},[140,368,171],{"class":146},[140,370,371],{"class":174}," room",[140,373,178],{"class":146},[140,375,354],{"class":150},[140,377,378],{"class":184},"setApp",[140,380,188],{"class":150},[140,382,226],{"class":157},[140,384,385],{"class":150},").",[140,387,388],{"class":184},"setRoom",[140,390,188],{"class":150},[140,392,393],{"class":157},"'general'",[140,395,229],{"class":150},[140,397,398,401,403,405,407],{"class":142,"line":262},[140,399,400],{"class":150},"room.",[140,402,221],{"class":184},[140,404,188],{"class":150},[140,406,243],{"class":157},[140,408,229],{"class":150},[140,410,411],{"class":142,"line":279},[140,412,165],{"emptyLinePlaceholder":164},[140,414,415,417,420,422,424,426,428,430,432],{"class":142,"line":285},[140,416,400],{"class":150},[140,418,419],{"class":184},"on",[140,421,188],{"class":150},[140,423,243],{"class":157},[140,425,246],{"class":150},[140,427,250],{"class":249},[140,429,253],{"class":150},[140,431,256],{"class":146},[140,433,259],{"class":150},[140,435,436,438,440,442,444],{"class":142,"line":290},[140,437,265],{"class":150},[140,439,268],{"class":184},[140,441,188],{"class":150},[140,443,273],{"class":157},[140,445,276],{"class":150},[140,447,448],{"class":142,"line":297},[140,449,282],{"class":150},[140,451,453],{"class":142,"line":452},12,[140,454,165],{"emptyLinePlaceholder":164},[140,456,458],{"class":142,"line":457},13,[140,459,460],{"class":293},"// Publish from any authorised client:\n",[140,462,464,466,469,471,473,476,479],{"class":142,"line":463},14,[140,465,400],{"class":150},[140,467,468],{"class":184},"emit",[140,470,188],{"class":150},[140,472,243],{"class":157},[140,474,475],{"class":150},", { text: ",[140,477,478],{"class":157},"'Hello!'",[140,480,200],{"class":150},[11,482,483,484,487,488,491],{},"The shape is the same. The main differences are that NoLag groups topics inside a ",[29,485,486],{},"room"," (so you get natural namespacing and presence per room), and access is controlled with ",[29,489,490],{},"actors and tokens"," rather than a per-channel auth endpoint.",[15,493,495],{"id":494},"auth-delete-your-auth-endpoint","Auth: delete your auth endpoint",[11,497,498,499,502],{},"Pusher private and presence channels call back to an auth endpoint you host, on every subscribe. NoLag does not need one. A connection authenticates once with an ",[29,500,501],{},"actor access token",", and what that actor can read or write is enforced at the broker with per-topic ACL, so there is no per-subscribe round-trip to your server.",[11,504,505,506,511],{},"For browser clients, mint a short-lived JWT (",[507,508,510],"a",{"href":509},"/docs/client-tokens","client token",") on your backend, signed with a project signing key. No NoLag API call is needed to issue one, and it expires on its own within minutes, so a long-lived secret never reaches the browser.",[15,513,515],{"id":514},"presence","Presence",[11,517,518,519,522],{},"Pusher presence channels map to NoLag ",[507,520,514],{"href":521},"/docs/concepts/presence",", tracked per room. You get join and leave events and the current member list without standing up your own tracking.",[15,524,526],{"id":525},"next-steps","Next steps",[23,528,529,537,545],{},[26,530,531,532,536],{},"Follow the ",[507,533,535],{"href":534},"/docs/getting-started","5-minute quick start"," to connect for the first time.",[26,538,539,540,544],{},"If you are building chat, the ",[507,541,543],{"href":542},"/docs/high-level-sdks","chat blueprint"," gives you rooms, typing, and history out of the box.",[26,546,547,548,552],{},"Compare the platforms in more detail: ",[507,549,551],{"href":550},"/compare/pusher","NoLag vs Pusher",".",[554,555,556],"style",{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":136,"searchDepth":161,"depth":161,"links":558},[559,560,561,562,563,564,565],{"id":17,"depth":161,"text":18},{"id":47,"depth":161,"text":48},{"id":128,"depth":161,"text":129},{"id":303,"depth":161,"text":304},{"id":494,"depth":161,"text":495},{"id":514,"depth":161,"text":515},{"id":525,"depth":161,"text":526},"Migration Guide","2026-07-29","A practical guide to moving a realtime app from Pusher Channels to NoLag, with a concept map and before-and-after code for subscribing and publishing.",null,"md",{},"/blog/migrate-from-pusher-to-nolag","6 min read",{"title":5,"description":568},"blog/migrate-from-pusher-to-nolag","wb75aaJuOZueIaEiMORktOwIB4bVVlAxDEzR_toHp3M",1788160341284]