Back to News & Insights
JavaScript October 11, 2026 · 9 min read

Build a REST API with Fairyfly and SQLite

I've been building Fairyfly, a lightweight, backend-focused JavaScript runtime built with Zig and...

Build a REST API with Fairyfly and SQLite

I've been building Fairyfly, a lightweight, backend-focused JavaScript runtime built with Zig and powered by QuickJS.

One of my goals with Fairyfly is to make backend development straightforward: write JavaScript, start an HTTP server, handle requests, and interact with a database without having to assemble a large stack of dependencies.

In this tutorial, we'll build a small REST API using Fairyfly's native HTTP server and SQLite APIs.

We'll create a task manager API that supports creating, retrieving, updating, and deleting tasks.

By the end, we'll have a working backend with persistent database storage, input validation, and appropriate HTTP status codes.

| Method | Endpoint | Description | | --- | --- | --- | | GET | /api/health | Check server health | | GET | /api/tasks | Retrieve all tasks | | POST | /api/tasks | Create a task | | GET | /api/tasks/:id | Retrieve a specific task | | PATCH | /api/tasks/:id | Update a task | | DELETE | /api/tasks/:id | Delete a task |

We'll use SQLite to store tasks locally. This means the data will remain available after the server restarts.

No Express, no external database server, and no npm dependencies are required for this example. Install Fairyfly

If you haven't installed Fairyfly yet, follow the installation instructions in the GitHub repository.

Our entire backend will live in this file. We'll use Fairyfly's built-in APIs directly instead of importing a web framework. Start with Fairyfly's HTTP server

First, http.serve() starts the HTTP server. Its handler receives three arguments: url, method, and body.

Unlike frameworks that give you a request object, this handler receives the URL, HTTP method, and request body as separate values. The body is a string, so we need to parse JSON ourselves when accepting JSON requests.

Second, the handler returns a Response. We can use Response.json() when we want to return JSON, including a specific HTTP status code.

For the task manager, we'll expand this simple handler into a complete API. Build the REST API

The CREATE TABLE IF NOT EXISTS statement creates our table on the first run. The table contains an automatically generated ID, a title, a completion flag, and a creation timestamp.

Fairyfly exposes SQLite through its built-in Database API, so we don't need to install a separate JavaScript database package.

The database file is relative to the current working directory. Running ff server.js from our project directory keeps tasks.db there.

For example, a request containing an invalid JSON body should return 400 Bad Request, rather than causing an unhandled parsing error.

Want to discuss this further?

Book a free strategy call with our team to see how these insights apply to your specific business goals.

Book a consultation