コンテンツにスキップ
公式サイト →

ストレージとデータ

TODO(内部向け・リリース前に対応して削除)

Section titled “TODO(内部向け・リリース前に対応して削除)”

Keelson のアプリには、2種類のファイルシステム領域があります。

領域再デプロイ時用途
アプリディレクトリ(ソースコード等)置き換わるアプリのコード、依存パッケージ
/data残るデータベース、アップロードファイル、永続データ

永続化したいものは /data に置いてください。 それ以外の場所に書き込んだデータは、再デプロイ時に失われます。

/data はアプリごとに分離されており、他のアプリからはアクセスできません。ワークスペース単位で容量が管理され、データは東京リージョンに保存されます。


/data には、アプリが必要とするあらゆるファイルを保存できます。

  • SQLite データベース — 顧客管理、案件管理、ログなどのアプリデータ
  • アップロードファイル — ユーザーがフォームから送信した画像、PDF、CSV など
  • 生成済みレポート — 集計結果やエクスポートファイル
  • キャッシュデータ — 外部 API のレスポンスや計算結果の再利用
  • 設定ファイル — アプリが実行時に生成する設定やステートファイル

社内ツールでよくある使い方:

/data/main.db # アプリのメインデータベース
/data/uploads/ # ユーザーがアップロードしたファイル
/data/reports/ # 日次・週次で生成したレポート

/data に保存しない方がよいもの

Section titled “/data に保存しない方がよいもの”

以下は /data 以外の方法を検討してください。

  • 巨大なバイナリファイル — 動画ファイルや大容量のデータセットはストレージ容量を圧迫します。外部のオブジェクトストレージ(S3 互換サービスなど)を検討してください
  • 一時ファイル — 処理中だけ必要なファイルは /tmp を使い、処理後に削除してください
  • 再生成可能なキャッシュ — npm の node_modules やビルド成果物は /data に置く必要はありません
  • 大規模ログの長期保存 — アプリログは Keelson のログ機能で閲覧できます。独自の大量ログを /data に蓄積するとストレージを消費します
  • 高い可搬性が求められるデータ — 他のシステムとの頻繁なデータ連携が必要な場合は、外部データベースが適しています

SQLite は Keelson でもっとも推奨されるデータベースです。外部の DB サーバーを用意する必要がなく、/data にファイルを置くだけで使えます。

  • セットアップ不要 — DB サーバーの構築・接続設定が不要
  • AI 生成との相性 — ChatGPT や Claude が生成するアプリの多くは SQLite を使う構成になる
  • 永続化が自動/data に置けば再デプロイ後もデータが残る
  • バックアップ対象 — 日次スナップショットの対象に含まれる
databases:
- name: main
type: sqlite
path: /data/main.db

複数のデータベースを使うこともできます。

databases:
- name: customers
type: sqlite
path: /data/customers.db
- name: logs
type: sqlite
path: /data/logs.db
  • 単一インスタンス前提 — Keelson のアプリは1つのインスタンスで動作します。複数インスタンスからの同時書き込みを考慮する必要はありません
  • 書き込みが非常に多い場合 — 秒間数百回以上の書き込みが発生するようなケースでは、外部データベース(PostgreSQL など)を検討してください
  • データ量が大きい場合 — 数 GB を超える SQLite ファイルはパフォーマンスに影響する可能性があります。データ量が大きくなる見込みがある場合は、早めに外部 DB への移行を計画してください

ユーザーがアップロードしたファイルは /data 配下に保存します。

/data/uploads/
├── 2026-03/
│ ├── a1b2c3d4-report.pdf
│ └── e5f6g7h8-photo.jpg
└── 2026-04/
└── i9j0k1l2-invoice.csv

ユーザーがアップロードしたファイル名をそのまま使うと、同名ファイルが上書きされます。UUID やタイムスタンプをプレフィックスに付けてください。

import uuid, os
def save_upload(file, upload_dir="/data/uploads"):
filename = f"{uuid.uuid4().hex}_{file.filename}"
path = os.path.join(upload_dir, filename)
with open(path, "wb") as f:
f.write(file.read())
return path

ストレージ容量はプランによって異なります(Starter: 10 GB 〜 Business: 100 GB)。この容量には /data のデータ、スナップショット、ログの合計が含まれます。

不要になったファイルは定期的に削除する仕組みを入れておくと安心です。定期実行ジョブ(cron)で古いファイルを自動削除するのも有効です。

  • アップロードされたファイルの拡張子やサイズを検証してください
  • ユーザーが指定したファイル名をそのままパスに使わないでください(ディレクトリトラバーサルの防止)
  • Keelson の認証プロキシにより、アプリ自体へのアクセスは保護されていますが、アプリ内でのファイルアクセス制御はアプリ側の責務です

Keelson は /data のスナップショットを毎日自動で取得します。保持日数はプランによって異なります。

プランスナップショット保持
Starter1日分
Plus3日分
Team7日分
Business14日分

手動スナップショットは、SQLite 管理画面から任意のタイミングで取得できます(全プラン)。

対象バックアップされるか
/data 配下のファイル(SQLite、アップロードファイルなど)される
アプリのソースコードされない(デプロイ時に毎回送信される)
環境変数されない(ダッシュボードで管理)

アプリのコードは Git などのバージョン管理で保持し、データは Keelson のスナップショットで保護されます。

スナップショットからの復元が必要な場合は、ダッシュボードから操作できます。復元はアプリ単位で行われ、他のアプリのデータには影響しません。


外部データベースや外部ストレージを使うべき場合

Section titled “外部データベースや外部ストレージを使うべき場合”

/data + SQLite は多くの社内アプリに十分ですが、以下のケースでは外部サービスの利用を検討してください。

ケース理由選択肢
データ量が数 GB を超えるSQLite のパフォーマンスが低下する可能性PostgreSQL(アドオンで専用 DB を利用可能)
同時書き込みが非常に多いSQLite はライター1つの制約があるPostgreSQL、MySQL
BI や基幹系と直接連携するデータを外部システムから参照する必要がある共有の PostgreSQL、データウェアハウス
厳密な運用要件があるポイントインタイムリカバリや複雑なレプリケーションが必要マネージド PostgreSQL
大容量ファイルを大量に扱うストレージ容量を超える可能性S3 互換オブジェクトストレージ

顧客管理や在庫管理など。SQLite にデータを保存し、アップロードファイルも /data に配置。

databases:
- name: main
type: sqlite
path: /data/main.db
/data/
├── main.db
└── uploads/

CSV の取込・加工を行うアプリ。入力と出力を分離して管理。

/data/
├── inbox/ # 取込対象の CSV
├── outbox/ # 加工済みの出力
└── processed/ # 処理済みの入力(アーカイブ)

社内 RAG や AI チャットのバックエンド。ナレッジベースのデータや添付資料を /data に配置。

/data/
├── knowledge.db # ナレッジのメタデータ
├── documents/ # 参照ドキュメント
└── embeddings.cache # 前処理済みの埋め込みキャッシュ

定期実行ジョブで集計し、結果を /data に保存。Web UI から閲覧。

/data/
├── stats.db
└── reports/
├── 2026-03-01.json
├── 2026-03-02.json
└── ...

/tmp やアプリディレクトリに保存して消える

Section titled “/tmp やアプリディレクトリに保存して消える”

/tmp やアプリのソースコードと同じディレクトリに書き込んだデータは、再デプロイ時に失われます。永続化したいデータは必ず /data に置いてください。

# NG — 再デプロイで消える
db_path = "./data.db"
db_path = "/tmp/data.db"
# OK — 再デプロイ後も残る
db_path = "/data/main.db"

再デプロイで初期化される場所に DB を置く

Section titled “再デプロイで初期化される場所に DB を置く”

SQLite のパスを /data 以外に設定すると、デプロイのたびにデータが消えます。keelson.yamldatabases[].path/data/ で始まっていることを確認してください。

バックアップの仕組みを誤解する

Section titled “バックアップの仕組みを誤解する”

スナップショットは日次で自動取得されますが、保持日数はプランによって異なります。重要なデータを扱う場合は、プランの保持日数を確認し、必要に応じてアプリ側でもエクスポート機能を用意してください。

不要になったファイルを削除せずに放置すると、ストレージ容量を圧迫します。ストレージ容量にはスナップショットやログも含まれるため、アプリデータだけで上限いっぱいにならないよう注意してください。

ローカルのパスをハードコードする

Section titled “ローカルのパスをハードコードする”

/Users/tanaka/Desktop/data.db のようなローカルパスがコードに残っていると、Keelson 上では動作しません。環境変数または /data への相対的なパスを使ってください。

import os
# OK — 環境変数から読む
db_path = os.environ.get("DB_PATH", "/data/main.db")

Python: SQLite でデータを保存する

Section titled “Python: SQLite でデータを保存する”
import sqlite3, os
DB_PATH = os.environ.get("DB_PATH", "/data/main.db")
def get_db():
conn = sqlite3.connect(DB_PATH)
conn.execute("""
CREATE TABLE IF NOT EXISTS items (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
""")
return conn
# データの追加
conn = get_db()
conn.execute("INSERT INTO items (name) VALUES (?)", ("サンプルアイテム",))
conn.commit()
conn.close()

keelson.yaml:

slug: my-app
runtime: python-slim
command: "pip install --user -r requirements.txt && python app.py"
env:
PORT: "8080"
DB_PATH: "/data/main.db"
databases:
- name: main
type: sqlite
path: /data/main.db

Node.js: SQLite でデータを保存する

Section titled “Node.js: SQLite でデータを保存する”
const Database = require("better-sqlite3");
const path = process.env.DB_PATH || "/data/main.db";
const db = new Database(path);
db.exec(`
CREATE TABLE IF NOT EXISTS items (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
)
`);
// データの追加
db.prepare("INSERT INTO items (name) VALUES (?)").run("サンプルアイテム");

Python: ファイルアップロードを保存する

Section titled “Python: ファイルアップロードを保存する”
from fastapi import FastAPI, UploadFile
import uuid, os
app = FastAPI()
UPLOAD_DIR = os.environ.get("UPLOAD_DIR", "/data/uploads")
os.makedirs(UPLOAD_DIR, exist_ok=True)
@app.post("/upload")
async def upload(file: UploadFile):
filename = f"{uuid.uuid4().hex}_{file.filename}"
filepath = os.path.join(UPLOAD_DIR, filename)
with open(filepath, "wb") as f:
content = await file.read()
f.write(content)
return {"filename": filename, "path": filepath}

Node.js: ファイルアップロードを保存する

Section titled “Node.js: ファイルアップロードを保存する”
const express = require("express");
const multer = require("multer");
const crypto = require("crypto");
const path = require("path");
const fs = require("fs");
const app = express();
const uploadDir = process.env.UPLOAD_DIR || "/data/uploads";
fs.mkdirSync(uploadDir, { recursive: true });
const storage = multer.diskStorage({
destination: uploadDir,
filename: (req, file, cb) => {
const prefix = crypto.randomBytes(8).toString("hex");
cb(null, `${prefix}_${file.originalname}`);
},
});
app.post("/upload", multer({ storage }).single("file"), (req, res) => {
res.json({ filename: req.file.filename, path: req.file.path });
});

  • 社内アプリの業務データ — 顧客情報、案件、在庫など、SQLite で十分な規模
  • ユーザーがアップロードするファイル — PDF、CSV、画像など
  • AI で生成したアプリをすぐに動かしたい — 外部 DB の設定なしでデータ永続化が使える
  • 小さなアプリを複数動かしたい — アプリごとに /data が分離されている
  • データ量が数十 GB を超える — ストレージ容量とパフォーマンスの両面で外部 DB を検討
  • 複数システムからの同時アクセスが必要/data はアプリ内からのみアクセス可能
  • ポイントインタイムリカバリが必須 — スナップショットは日次のため、より細かい復元が必要ならマネージド DB を検討
  • BI ツールや基幹システムとの直接連携 — 外部からクエリできるデータベースが必要

/data の容量上限はどのくらいですか?

Section titled “/data の容量上限はどのくらいですか?”

プランによって異なります(Starter: 10 GB 〜 Business: 100 GB)。この容量には /data のデータ、スナップショット、ログの合計が含まれます。追加ストレージはアドオンで購入できます。

再デプロイするとデータは消えますか?

Section titled “再デプロイするとデータは消えますか?”

/data に保存したデータは消えません。アプリのソースコード領域は置き換わりますが、/data は再デプロイ後もそのまま残ります。

SQLite 以外のデータベースは使えますか?

Section titled “SQLite 以外のデータベースは使えますか?”

アプリ内で完結するデータベース(SQLite など)はそのまま使えます。外部の PostgreSQL や MySQL に接続することも可能です。アドオンで専用 PostgreSQL を利用することもできます。

他のアプリから /data にアクセスできますか?

Section titled “他のアプリから /data にアクセスできますか?”

できません。/data はアプリごとに完全に分離されています。アプリ間でデータを共有する必要がある場合は、API 経由でやり取りしてください。

バックアップからの復元にかかる時間はどのくらいですか?

Section titled “バックアップからの復元にかかる時間はどのくらいですか?”

データ量によりますが、一般的な社内アプリの規模であれば数分で完了します。


「データベースは SQLite を使い、/data/main.db に保存してください」

「アップロードされたファイルは /data/uploads/ に UUID 付きのファイル名で保存してください」

「環境変数 DB_PATH からデータベースのパスを読み取るようにしてください。デフォルトは /data/main.db です」