Deliver Fast Apps Globally

Harper is an open source Node.js performance platform that unifies database, cache, application, and messaging layers into one in-memory process. Build faster. Scale globally. Lead with performance.
Illustration of the Harper application platform stack showing GraphQL, API, REST, WebSocket, and MQTT on top of Cache and In-Memory layers, above Blob, Database, NoSQL, and Vector storage, all powered by a globally distributed Harper Fabric.
Accelerating Innovation For
AGENTIC ENGINEERING

Describe It.
Ship It.
Scale It.

Most stacks split code and infrastructure. Harper unifies them in declarative files so your AI agent can build, change, and deploy your apps on demand.
Learn More
White arrow pointing right
~/my-app
⚡ Agent reading skills/…
schemas.md rest-apis.md real-time.md caching.md vector-search.md deploy.md
Schema + REST API auto-generated
Real-time pub/sub built-in
Cache layer built-in
Deployed to Fabric 3 regions
🌐 my-app.harperdbcloud.com
+$8.6 M
Estimated annual revenue uplift from enhanced search engine indexation, delivering an 71x ROI.
+71%
Faster page loads delivering 33% top level growth.
+34%
Increase in mobile conversion rate due to an 80% increase cache hit ratio.

How Much More Could You Earn?

High-performing websites drive greater engagement, boost conversion rates, and fuel revenue growth.
Calculate Uplift

All Functions. One Platform.

Build apps that outperform their multi-system solutions.

The schema is the server.

Define tables in GraphQL. Harper instantly exposes a full REST API, no controllers, no routes, no ORM. Change the schema, the API updates with it.
Documentation
// schema.graphql

type Dog @table @export {
  id:        ID       @primaryKey
  name:      String
  breed:     String   @indexed
  age:       Int
  status:    String    # available | adopted | fostered
  bio:       String
  tricks:    [String]
  embedding: [Float]  @indexed(type: "HNSW", distance: "cosine")
  photo:     Blob
  owner:     Owner    @relationship(from: "ownerId")
  ownerId:   ID       @indexed
}

type Owner @table @export {
  id:    ID     @primaryKey
  name:  String
  phone: String
  city:  String
}

// You immediately get:
GET     /Dog/{id}
POST    /Dog/
PUT     /Dog/{id}
PATCH   /Dog/{id}
DELETE  /Dog/{id}
GET     /Dog/?breed=Labrador&sort(-age)

GET     /Owner/{id}
POST    /Owner/
...

// No migrations. No REST framework. No code generation step.

Query Your Way: URL, fetch, or GraphQL

Filter, sort, join, and paginate from a URL, a fetch call, or the native GraphQL endpoint, all against the same data, no adapter needed.
Documentation
// 1st Let's start by adding data. Add as much as you want. 

POST /Owner/
Content-Type: application/json
{
  "name": "John Smith",
  "phone": "123-456-7890",
  "city": "Denver"
}

POST/Dog/
Content-Type: application/json
{
  "name": "Rex",
  "breed": "Labrador",
  "age": 5,
  "status": "available",
  "bio": "Loves fetch and long walks",
  "tricks": ["sit", "shake", "fetch"],
  "ownerId": "<copy id from `POST /Owner/`>"
}

// 2nd Now let's filter, sort, and traverse relationships in the address bar with URL querys

// Senior dogs available for adoption
GET /Dog/?age=gt=7&status=available&sort(-age)&limit(10)

// Breed is "Retriever", status is available OR fostered
GET /Dog/?breed=Retriever&(status=available|status=fostered)

// Join through the owner relationship
GET /Dog/?owner.city=Austin&select(name,breed,owner{name,phone})


// fetch — same filters, works anywhere JS runs
const res = await fetch(
  '/Dog/?breed=Retriever&status=available&select(name,breed,age)',
  { headers: { Authorization: 'Basic ' + btoa('user:pass') } }
);
const dogs = await res.json();


// GraphQL — enable with one line in config.yaml, query /graphql
{
  Dog(status: "available") {
    name
    breed
    age
    owner {
      name
      phone
    }
  }
}

Custom Behavior, Zero New Services

Extend any table with a JavaScript class, computed fields, validation, side effects. It runs in-process alongside your data, no microservice, no extra network hop.
Documentation
// resources.js
import { tables } from 'harperdb';
const { Dog } = tables;

export class AdoptableDog extends Dog {
  // Enrich every GET with computed fields
  async get(query) {
    const dog = await super.get(query);
    return {
      ...dog,
      humanAge:  15 + dog.age * 5,
      isGoodBoy: true,  // always
    };
  }

  // Validate and set defaults on every POST
  async post(target, data) {
    if (!data.name) throw new Error('Every dog deserves a name');
    data.tricks = data.tricks ?? [];
    data.status = 'available';
    return super.post(target, data);
  }
}

// Three files. That's still the whole backend. 

Kill your Redis. Keep your speed.

Point a Harper resource at an external data source. Harper fetches, caches, and serves it, with configurable TTL and automatic stampede protection. No Redis, no middleware.
Documentation
// schema.graphql — cached for 1 hour 
type BreedImage @table(expiration: 3600) @export {
  id: ID @primaryKey
  image: String
}


// resources.js — point it at the dog.ceo API 
import { Resource, tables } from 'harperdb';

class DogCeoAPI extends Resource {
  async get() {
    const breed = this.getId();
    const res = await fetch(
      `https://dog.ceo/api/breed/${breed}/images/random`
    );
    const data = await res.json();
    return { breed, image: data.message };
  }
}

tables.BreedImage.sourcedFrom(DogCeoAPI);


// Cache miss fetches from dog.ceo API
GET /BreedInfo/labrador
// Cache hits return in <1ms
GET -H 'If-None-Match: "<Etag>"' /BreedInfo/labrador

Pub/sub is a Table Feature, Not a Separate Bill.

Subscribe to any record over Server-Sent Events, WebSocket, or MQTT, built in, no extra broker. When data changes, subscribers hear about it instantly.
Documentation
// 3 Examples of Real-Time In Action
// OPTION 1 | Server Sent Events (SSE), no library needed 
const events = new EventSource('/Dog/<id>/');

events.onmessage = (e) => {
  const data = JSON.parse(e.data);
  const dog = data.value;
  console.log(`${dog.name} is now: ${dog.status}`);
  // → "Rex is now: adopted"
};


// OPTION 2 | WebSocket with custom actions via resources.js
import { tables } from 'harperdb';

export class LiveDog extends Resource {
  async *connect(target, incomingMessages) {
    const subscription = await tables.Dog.subscribe(target);

    if (!incomingMessages) {
      return subscription;  // SSE mode
    }

    for await (let msg of incomingMessages) {
      if (msg.action === 'wag') yield { tail: 'wagging' };
    }
  }
}


// OPTION 3 | config.yaml — enable MQTT for IoT collar tracking 
mqtt:
  network:
    port: 1883
  webSocket: true
  requireAuthentication: true

Semantic Search without a Second Database.

The embedding field in your schema already has an HNSW index. Store vectors alongside your data and query them with the same REST API,  no separate vector database.
Documentation
// Already declared in schema.graphql (Tab 1:Schema):
// embedding: [Float] @indexed(type: "HNSW", distance: "cosine")


// Store a dog profile with its bio embedding

await fetch('/Dog/<id>', {
  method: 'POST',
  body: JSON.stringify({
    name:      'Biscuit',
    breed:     'Golden Retriever',
    bio:       'Loves fetch, belly rubs, and long walks',
    embedding: await getEmbedding('Loves fetch, belly rubs, and long walks'),
    status:    'available',
  }),
});


// Find the 5 most similar dogs to a query
import { tables } from 'harperdb';

const results = tables.Dog.search({
  select: ['name', 'breed', 'bio', '$distance'],
  sort: {
    attribute: 'embedding',
    target: await getEmbedding('friendly dog who loves walks'),
  },
  limit: 5,
});
// → dogs ranked by cosine similarity to the query vector 

No S3. No CDN. Just a field.

The photo field in your schema is a native Blob. Upload and serve binary files from the same endpoint as your data, no S3 bucket, no file service.
Documentation
// Already declared in schema.graphql (Tab 1:Schema):
// photo: Blob 
// Upload and retrieve a dog photo

// Upload
PUT /Dog/<id>/photo
Content-Type: image/jpeg
< ./rex-headshot.jpg

// Retrieve — streams back with correct Content-Type
GET /Dog/<id>/photo


// Upload from a browser form 
const formData = new FormData();
formData.append('photo', fileInput.files[0]);

await fetch('/Dog/<id>/photo', {
  method: 'PUT',
  body: formData,
});

Deploy your Backend Like you Push Your Code

Deploy your entire backend, database, API, cache, logic, real-time, vector search, etc., to Harper Fabric's distributed network with a single command. No containers, no Kubernetes, no cloud console.
Documentation
// Develop locally
harper dev .

// Deploy local project to Fabric (push-based deploys)
cd my-app
harper deploy . 
  project=my-app \
  target="https://your-app.fabric.harper.fast/" \
  username="your-cluster-username" \
  password="your-cluster-password" \
  restart=rolling \
  replicated=true

// Deploy GitHub project to Fabric (pull-based deploys)
harper deploy \
  project=my-app \
  package="https://github.com/User/my-app" \
  target="https://your-app.fabric.harper.fast/" \
  username="your-cluster-username" \
  password="your-cluster-password" \
  restart=rolling \
  replicated=true

// Same API. Same schema. Same logic. Just… everywhere.
GET https://your-app.fabric.harper.fast/Dog/?breed=Labrador&status=available

// No Dockerfile. No cloud console wizards.
// All your files → one command → globally distributed. 

Open Source Applications

Jumpstart your next build with open source projects.

Start Here

Enterprise Strategy and Execution

All Resources

Solutions for Enterprises

All Solutions

SAVE YOUR SPOT

Request a Free Pilot

Make performance your competitive edge. Harper’s pilot program helps engineering leaders achieve breakthrough results. With limited availability and high demand, now is the time to claim your free pilot.
Glowing neon checkmark in blue and pink hues, bursting outward with shards and energy effects, symbolizing success or completion in a dynamic, futuristic style.

You’re on the list!

Our solutions team will reach out shortly to confirm next steps. With over 90% of pilots succeeding, you’ve just taken the fastest path to higher performance. Congratulations!
Please review the form. Some information couldn’t be processed.