← All articles

Skapi 2.0 is out as a release candidate

Skapi 2.0 is installable today as a release candidate. It is a stability and performance release: a naming change, one genuinely new method, and a long run of fixes behind both.

Skapi
npm i skapi-js@rc

The stable tag has not moved. A plain npm i skapi-js still installs 1.8.3, so nothing you are running changes until you ask for it.

Where this started

The first Skapi commit is dated November 3, 2022. The README opened with a single sentence, "skapi is a backend framework for frontend developers", and listed four things underneath it: an auto indexed scalable database, authentication, cloud storage, and email newsletters. And at the bottom of the file, one more line. "We have just released an alpha!"

The goal has not moved since. Build a whole web backend that needs no server deployment, no database schema design, no backend configuration and no terminal. Just an API you call from the browser, and it works: authentication, email, cloud storage, database, realtime over WebSocket and WebRTC. Everything a professional web service needs. That was the whole complaint, and it is not a subtle one. Setting up infrastructure was eating the fortnight we wanted to spend building the thing we came to build.

The first stable release, 1.0.0, arrived on October 10, 2023, eleven months after that alpha, and the documentation site was started the same day. In all: 2,500 commits and 907 versions published to npm, with work landing in every year from 2022 to 2026. Three years and nine months to reach a version number that starts with a 2.

We are proud of that, and the specific thing we are proud of is that the sentence from the 2022 README is still true:

Serverless Backend API for Web Developers

Three decisions, all made early, all still holding the thing up.

Serverless infrastructure, region by region. The regional backend runs on serverless functions. There is no central server for you to deploy, patch, scale, or pay for while it sits idle.

A client centric security model. In a traditional stack the central server decides how data is indexed and who is allowed to read or edit it. That is a large part of why so many backends end up as one monolith: those rules have to live somewhere every request passes through. Skapi moves the decision to the client, which declares the data structure and the access rules before the data is uploaded. Removing the central authority is what removed the central server.

Lexicographic database indexing. Skapi asks you to predefine nothing. A table is created when you write the first record into it, and removed when the last record leaves. Queries still work because every indexed record is stored under a composite key that packs the index name together with a typed, lexically ordered form of its value. A range read over those ordered keys does the work a schema would usually do. It is a plain storage format carrying very little overhead, which is what keeps a flexible query cheap as the table grows.

Changes in v2

Most of v2 is stability and performance work rather than new features, and it goes out of its way not to break your existing code.

A service is now a project

What used to be a Service is now a Project. A project is the complete backend for one application, and your frontend connects to it in one line.

const skapi = new Skapi("<Project ID>");

That is a naming change, not a migration. The old identifiers are still accepted, the older spellings stay exactly where they are, and your existing code needs no edit for any of it.

A more stable polling system

Skapi can call a third party API for you, so the key never reaches the browser. You register the secret once, and it is filled in on the server as the call goes out.

Those calls are rarely quick, so the client waits and asks again until the answer lands. How often it asks is yours to set.

You can also drop calls into a named queue, and a queue runs them strictly one at a time, in the order you made them. That is worth having when the order is the whole point: the charge before the receipt, the write before the read that depends on it. We tightened how those queues are identified along the way, so two different APIs that happened to share a queue name no longer report each other's requests.

Nothing in a queue disappears quietly either. Every request settles into a state you can look up, a failure comes back with the reason attached, and one failure does not take the rest of the queue down with it.

Temporary urls that expire like they mean it

A private file is never served from a permanent address. Every read mints a temporary signed url, and 2.0 tightened what that url is worth to anyone who is not you.

The url lives an hour. Long enough to be useful, short enough that a copy of it is not a standing grant on your file. That matters more than it used to, because a file you hand to an AI assistant is a url that lands in a third party platform's conversation history, logs and context window. When it expires, the copy stops working. It was never a key to your storage, only a ticket with a clock on it.

Fewer surprises from session storage

Skapi saves a snapshot of itself when you leave the tab, so coming back is quick. On a busy project that snapshot outgrew the room the browser gives it, and switching tabs threw an error at you every single time.

It saves less now instead of failing. The cached pages are the first thing dropped, and if there is still no room, the old snapshot is thrown away rather than restored over a session it no longer matches. Losing a cache costs you one refetch. Restoring the wrong one costs you correctness.

Why this is a 2.0

None of that is a feature you call. It is how the SDK behaves under load, across a long session, and around data that is not yours. Those are the parts nobody thinks about until they fail, and they are the parts this release went into.

We would rather ship a version that makes the quiet layer trustworthy than one that adds another method to the list. These felt significant enough to be the next step for Skapi rather than another point release, and that is why the number moved to 2.

Just a tiny breaking change...

Exactly one call is renamed. skapi.util.decodeServiceId() is now skapi.util.decodeProjectId().

That's about it for the whole 2.0 migration. Enjoy building with Skapi!

Baksa, Creator of BunnyQuery