[{"data":1,"prerenderedAt":420},["ShallowReactive",2],{"blog-en-supabase-new-api-keys":3},{"id":4,"title":5,"body":6,"category":383,"cover":384,"coverAlt":384,"description":385,"draft":386,"extension":387,"faq":388,"image":401,"keywords":402,"meta":408,"navigation":409,"ogTitle":410,"path":411,"published":412,"seo":413,"stem":414,"tldr":415,"updated":412,"__hash__":419},"blog_en\u002Fblog\u002Fsupabase-new-api-keys.md","Supabase's new API keys: which one is safe in your app?",{"type":7,"value":8,"toc":372},"minimark",[9,29,32,37,48,79,87,94,100,104,107,113,118,122,125,211,218,226,230,233,268,271,280,284,293,319,328,332,359],[10,11,12,13,17,18,21,22,17,25,28],"p",{},"If you opened your Supabase dashboard recently and found keys that start with\n",[14,15,16],"code",{},"sb_publishable_"," and ",[14,19,20],{},"sb_secret_"," sitting where ",[14,23,24],{},"anon",[14,26,27],{},"service_role"," used\nto be, nothing has gone wrong. Supabase renamed its API keys, and the pair you\nknew is on its way out.",[10,30,31],{},"The change is small in what it does and large in what it prevents. The two keys\nstill do exactly the two jobs they always did. What is new is that you can now\ntell which is which without opening anything.",[33,34,36],"h2",{"id":35},"what-supabase-actually-changed","What Supabase actually changed",[10,38,39,40,47],{},"Supabase ",[41,42,46],"a",{"href":43,"rel":44},"https:\u002F\u002Fsupabase.com\u002Fblog\u002Fjwt-signing-keys",[45],"nofollow","announced the new keys in July 2025",",\nalongside a change to how it signs authentication tokens. Two things replaced\ntwo things:",[49,50,51,67],"ul",{},[52,53,54,55,59,60,63,64,66],"li",{},"The ",[56,57,58],"strong",{},"publishable"," key, ",[14,61,62],{},"sb_publishable_…",", replaces the ",[14,65,24],{}," key.",[52,68,69,72,73,76,77,66],{},[56,70,71],{},"Secret"," keys, ",[14,74,75],{},"sb_secret_…",", replace the ",[14,78,27],{},[10,80,81,82,86],{},"The privileges are unchanged. A publishable key still identifies your project\nand carries no permissions of its own; a secret key still bypasses every rule\nyou have written. If you already know\n",[41,83,85],{"href":84},"\u002Fblog\u002Fwhich-api-keys-are-safe-in-your-frontend","which keys are safe in a frontend",",\nnone of that intuition is now wrong.",[10,88,89,90,93],{},"Two practical differences are worth knowing. You can hold ",[56,91,92],{},"several"," secret\nkeys at once and revoke them one at a time, which means rotating a key no longer\nmeans a moment where everything that used it is broken. And the old keys had a\nproperty most people never noticed: they were JWTs that expire ten years after\nyou create the project. The new ones do not carry an expiry inside them.",[95,96],"diagram",{"alt":97,"caption":98,"src":99},"Two keys drawn one above the other. The older key is three chunks separated by dots, with the middle chunk opened up to show the word role. The newer key is one string, with its opening word sb underscore secret highlighted at the front.","Same two jobs, two different shapes. In the old pair the role is buried in the middle; in the new pair it is the first thing you read.","\u002Fblog\u002Fsupabase-new-api-keys\u002Ftwo-key-formats-1600x640.png",[33,101,103],{"id":102},"which-of-the-two-belongs-in-your-app","Which of the two belongs in your app",[10,105,106],{},"The publishable key, and only the publishable key.",[10,108,109,110,112],{},"Your app runs in your visitor's browser, and the request to your database goes\nout from there. It has to say which project it belongs to, and that identifier\ntravels to every visitor by design. ",[14,111,62],{}," is the key built for\nthat: finding it in your app is not a finding, and it never was.",[10,114,115,117],{},[14,116,75],{}," is the opposite. It reads and writes every row in every table from\nanywhere, ignoring your policies entirely, which is the whole point of it. It\nbelongs on a server, in an edge function, in a worker. Nowhere a browser can\nreach. If one has ever been pasted into frontend code, rotate it in the\ndashboard before you edit anything, because deleting the line does not close the\ndoor.",[33,119,121],{"id":120},"how-to-tell-which-kind-you-have","How to tell which kind you have",[10,123,124],{},"Read the first few characters. That is the entire check now.",[126,127,128,144],"table",{},[129,130,131],"thead",{},[132,133,134,138,141],"tr",{},[135,136,137],"th",{},"What you see",[135,139,140],{},"What it is",[135,142,143],{},"Safe in the browser?",[145,146,147,164,179,196],"tbody",{},[132,148,149,154,157],{},[150,151,152],"td",{},[14,153,62],{},[150,155,156],{},"current publishable key",[150,158,159],{},[160,161,163],"key-verdict",{"type":162},"safe","Belongs here",[132,165,166,170,173],{},[150,167,168],{},[14,169,75],{},[150,171,172],{},"current secret key",[150,174,175],{},[160,176,178],{"type":177},"danger","Never",[132,180,181,189,192],{},[150,182,183,186,187],{},[14,184,185],{},"eyJ…"," with ",[14,188,24],{},[150,190,191],{},"legacy publishable key",[150,193,194],{},[160,195,163],{"type":162},[132,197,198,204,207],{},[150,199,200,186,202],{},[14,201,185],{},[14,203,27],{},[150,205,206],{},"legacy secret key",[150,208,209],{},[160,210,178],{"type":177},[10,212,213,214,217],{},"A current key is one long string in two halves: a random middle and a short\nchecksum on the end. A legacy key is three chunks separated by dots, and the\nmiddle chunk is readable text rather than encryption, which is why telling the\nold pair apart meant decoding it and reading the ",[14,215,216],{},"role"," field.",[10,219,220,221,225],{},"If you find a key in your app and cannot tell which it is, our free scan reads\nyour live site from outside and names what it can see. It takes about 20 seconds\nand needs no account: ",[41,222,224],{"href":223},"\u002F#scan","scan your app",".",[33,227,229],{"id":228},"do-my-old-anon-and-service_role-keys-still-work","Do my old anon and service_role keys still work?",[10,231,232],{},"Today, yes. Supabase has published a timeline rather than a switch-off:",[126,234,235,245],{},[129,236,237],{},[132,238,239,242],{},[135,240,241],{},"When",[135,243,244],{},"What happens",[145,246,247,260],{},[132,248,249,252],{},[150,250,251],{},"1 November 2025",[150,253,254,255,17,257,259],{},"Projects restored after this date no longer get ",[14,256,24],{},[14,258,27],{}," at all.",[132,261,262,265],{},[150,263,264],{},"Late 2026, exact date not set",[150,266,267],{},"All projects will be required to use the new keys.",[10,269,270],{},"So there is no emergency this week, and there is a deadline this year. If your\napp was built before the rename and has never been touched since, it is running\non legacy keys right now and will keep running on them for a while yet.",[10,272,273,274,276,277,279],{},"The case for moving early is not the deadline. It is that the day someone pastes\nthe wrong key into a prompt, ",[14,275,20],{}," announces itself and ",[14,278,185],{}," does not.",[33,281,283],{"id":282},"how-to-switch-without-breaking-your-app","How to switch without breaking your app",[10,285,286,287,292],{},"Supabase's own ",[41,288,291],{"href":289,"rel":290},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Fgetting-started\u002Fmigrating-to-new-api-keys",[45],"migration guide","\nis the reference. The short version, for an app you did not write by hand:",[294,295,296,303,306,313,316],"ol",{},[52,297,298,299,302],{},"In the dashboard, open ",[56,300,301],{},"Settings → API Keys"," and create the new keys. This\nadds them; it does not remove the old ones, and both pairs work at once.",[52,304,305],{},"Find where your app creates its Supabase client and replace the publishable\nkey. In a builder like Lovable or Bolt this is usually one value in your\nproject's settings rather than a line of code.",[52,307,308,309,312],{},"Replace the secret key anywhere it is used ",[56,310,311],{},"on a server",": edge functions,\nwebhooks, scheduled jobs, anything that is not the browser.",[52,314,315],{},"Load your app and click through the parts that read and write data. A wrong\npublishable key fails loudly and immediately, which is the good case.",[52,317,318],{},"Only once everything works, disable the legacy keys.",[10,320,321,322,324,325,327],{},"Step 5 is the one to leave for last, and it is worth doing deliberately rather\nthan never: half-migrated projects, where the app still carries a stale ",[14,323,24],{},"\nkey beside a live ",[14,326,16],{}," one, are common and confusing to debug.",[33,329,331],{"id":330},"what-to-do-this-week","What to do this week",[333,334,335],"key-takeaways",{},[49,336,337,340,349,352],{},[52,338,339],{},"Open Settings → API Keys and see which pairs your project has. That takes a minute and tells you where you stand.",[52,341,342,343,345,346,348],{},"If you find ",[14,344,75],{}," or ",[14,347,27],{}," anywhere in frontend code, rotate it today. That is the only item here that is urgent.",[52,350,351],{},"Create the new keys and switch your app over when you have half an hour, not because of the deadline but because the prefix makes the next mistake obvious.",[52,353,354,355,225],{},"Check Row Level Security while you are in there. The new key changes nothing about what your policies allow, and ",[41,356,358],{"href":357},"\u002Fblog\u002Fsupabase-rls-on-but-table-still-public","switching RLS on is not the same as being protected",[10,360,361,362,366,367,371],{},"If you want the platform-specific version of what to check, we have a plain\nlanguage walkthrough for ",[41,363,365],{"href":364},"\u002Fis-your-supabase-app-safe","Supabase apps",", and the\n",[41,368,370],{"href":369},"\u002Fchecklist","10-minute security checklist"," covers this alongside the other\nthings worth switching off in a newly launched app.",{"title":373,"searchDepth":374,"depth":374,"links":375},"",3,[376,378,379,380,381,382],{"id":35,"depth":377,"text":36},2,{"id":102,"depth":377,"text":103},{"id":120,"depth":377,"text":121},{"id":228,"depth":377,"text":229},{"id":282,"depth":377,"text":283},{"id":330,"depth":377,"text":331},"Security basics",null,"Supabase replaced anon and service_role with publishable and secret keys. Which one belongs in your app, and which never does?",false,"md",[389,392,395,398],{"q":390,"a":391},"Is sb_publishable_ the same as the anon key?","It does the same job. It names your project so a request knows where to go, it carries no permissions of its own, and it is meant to sit in your app where anyone can read it. What protects your data in both cases is Row Level Security, not the key.",{"q":393,"a":394},"Do my anon and service_role keys still work?","Yes, today. Supabase has kept them working through the migration and you can hold both pairs at once. It has said that in late 2026 all projects will be required to move to the new keys, without naming the exact day yet.",{"q":396,"a":397},"I have both pairs in my dashboard. Which one should my app use?","Use the publishable key, sb_publishable_. Switching is a one-line change: swap the key your app passes when it creates the Supabase client. Nothing about your tables or your policies changes, because the new key has exactly the privileges the anon key had.",{"q":399,"a":400},"Does the new key format make my app more secure on its own?","No. It makes the dangerous key easier to spot, which is worth real money in mistakes not made, but a publishable key still reads whatever your policies let it read. If Row Level Security is off, the new key opens your database exactly as wide as the old one did.","\u002Fblog\u002Fsupabase-new-api-keys\u002Fcard-800x500.png",[403,404,405,406,407],"supabase new api keys","sb_publishable key","sb_secret key","supabase anon key deprecated","supabase api key migration",{},true,"Supabase's new API keys, explained","\u002Fblog\u002Fsupabase-new-api-keys","2026-08-12",{"title":5,"description":385},"blog\u002Fsupabase-new-api-keys",[416,417,418],"Supabase now issues sb_publishable_ and sb_secret_ keys. They replace anon and service_role, and do the same two jobs.","The publishable key belongs in your app. The secret key never does, and now you can tell them apart by reading the first few characters.","Your old keys still work today. Supabase has said all projects will have to move off them in late 2026.","CWPJgTVXenqvsasbBcCp0Fq-qXqXTrlL6JI4rD4r8vI",1787826048204]