SSD Nodes Learn Hosting plans →
Rehberler Matt ConnorYazan Matt Connor · Güncellendi 2026-08-28

Kendi VPS Sunucunuzda mem0 Kurulumu ve RAM Gereksinimleri

mem0 bellek sunucusunu kendi VPS ortamınızda çalıştırmanın gerçek maliyetini öğrenin. 2 GB RAM ile FastAPI ve Postgres kurulumu, Ollama entegrasyonu ve kaynak yönetimi rehberi.

Bir VPS üzerinde mem0 barındırmanın gerçek RAM maliyeti

mem0'ı kendi sunucunuzda barındırmak, üç container çalıştırmak anlamına gelir: FastAPI bellek sunucusu, pgvector eklentili Postgres ve bir Next.js paneli. mem0, yapay zeka ajanları için bir bellek katmanıdır. Bir konuşmayı buraya gönderdiğinizde, bir dil modeli bu konuşmadan kalıcı gerçekleri çıkarır ve bu gerçekler, daha sonra ilgili olanların geri çağrılabilmesi için vektör olarak saklanır.

Üç container için yaklaşık 1 GB yerleşik bellek ve imajlar oluşturulduktan sonra 3 ila 4 GB disk alanı ayırın. Dil modeli başka bir yerde barındırıldığında, 2 GB RAM'e sahip bir VPS bu kurulumu rahatlıkla çalıştırır. Model, Ollama aracılığıyla aynı sunucuda çalıştırıldığında, model tüm kaynakları tüketir: 4 bit kuantize edilmiş 8B bir model tek başına yaklaşık 6 GB RAM gerektirir, bu nedenle tamamen yerel bir kurulum 8 GB RAM ile başlar.

Bu rakamları, bu yazı da dahil olmak üzere herhangi bir blog gönderisinden olduğu gibi almayın. Kendi oluşturduğunuz yığını ölçün.

docker compose ps
docker stats --no-stream
docker system df -v

docker stats, container başına yerleşik belleği yazdırır. docker system df -v, her imajın ve her birimin kapladığı disk alanını yazdırır.

Kararlı durum, tepe noktası değildir. docker compose up -d --build, Next.js panelini derler ve bu Node derleme süreci, tüm kurulumun en çok kaynak tüketen anıdır. 1 GB RAM'li bir VPS üzerinde çekirdeğin bellek yetersizliği sonlandırıcısı (OOM killer) bu işlemi durdurur ve derleme exit code 137 ile sona erer. Bir Docker hatası aramaya başlamadan önce nedeni doğrulayın:

dmesg -T | grep -i "killed process"

Bir sunucu, ihtiyaçlarınız için çok fazla donanım gerektiriyorsa, daha küçük seçenekler mevcuttur. hiç sunucu gerektirmeyen yerel bir ajan bellek deposu ve doğrudan Claude Code içinde yaşayan bellek, veritabanı ihtiyacını ortadan kaldırır. Birden fazla ajanın veya birden fazla makinenin aynı bellekleri okuması gerektiğinde buraya geri dönün.

mem0 grafik belleği için Neo4j gerekli mi?

Hayır. Eğer bir kılavuz size bir Neo4j container'ı eklemenizi söylüyorsa, o kılavuz koddan daha eskidir.

mem0 içindeki grafik belleği, eskiden graph_store anahtarı altında yapılandırılan ve enable_graph değeri true olarak ayarlanan harici bir grafik veritabanı anlamına geliyordu. Nisan 2026'da yayınlanan yeni bellek algoritması, her iki anahtarı da açık kaynak SDK'dan kaldırdı. Varlık çıkarımı (entity extraction) artık standart add yolu içinde çalışır ve varlıklar, ana koleksiyonunuzun adının sonuna _entities eklenerek oluşturulan ikinci bir pgvector koleksiyonuna yazılır. Çalıştırılması gereken bir taşıma işlemi yoktur. Yerleşik varlık bağlama (entity linking) özelliği, bir sonraki add çağrısıyla birlikte çalışmaya başlar.

Grafik deposunu kaldırmak; bir JVM container'ını, onun heap alanını ve birkaç yüz megabaytlık imaj boyutunu tasarruf etmenizi sağlar. 2 GB RAM'e sahip bir VPS üzerinde bu, sistemin çalışması ile swap alanına düşmesi arasındaki farktır.

Açıkça belirtmek gerekirse, vazgeçtiğiniz özellikler şunlardır: Arama sonuçları, varlıklar arasındaki kenarları listeleyen bir relations alanı taşıyordu. Bu alan artık kaldırıldı. Varlık eşleşmeleri artık belleğin birleşik skor içindeki konumunu yükseltir ve üzerinde gezinebileceğiniz bir yapı bulunmaz. Eğer uygulamanız bu ilişkiler üzerinde geziniyorsa, mem0 artık bunları tutmamaktadır; bu durumda kendi kodunuzla beslediğiniz bir grafik veritabanını mem0 dışında tutmaya devam etmelisiniz.

Depodaki compose dosyası bir geliştirme ortamı compose dosyasıdır

server/docker-compose.yaml, name: mem0-dev değerini tanımlar ve bu durum tam olarak ifade edildiği anlama gelir. Çalıştırmadan önce dosyayı okuyun; çünkü içerisinde sunucu ortamı için hatalı olan beş farklı yapılandırma bulunmaktadır.

  • Dosya, server/dev.Dockerfile üzerinden derleme yapar ve .:/app ile yerel dizininizi imajın üzerine bağlar (mount); bu nedenle container, derlediğiniz kodu değil, o dizinde o an ne varsa onu çalıştırır.
  • Komutu rm -rf /app/packages && pip install -q --force-reinstall --no-deps mem0ai && alembic upgrade head && uvicorn main:app --reload şeklindedir. Bu komut, her başlatma işleminde mem0ai paketini PyPI üzerinden yeniden kurar; dolayısıyla sunucunuzun çalıştırdığı sürüm, yükseltme yapmadığınızı düşündüğünüz bir yeniden başlatma sırasında değişebilir.
  • Aynı pip adımı, dış ağ bağlantısı olmadığında uvicorn çalışmadan önce işlemin başarısız olacağı anlamına gelir. PyPI'a erişilemediği için bellek sunucunuz devre dışı kalır.
  • --reload, uvicorn'un dosya izleyicisini başlatır. Bu araç, kod düzenlediğinizde süreci yeniden başlatmak için vardır; üretim ortamında hiçbir işe yaramaz ve ek bellek tüketerek fazladan bir süreç oluşturur. Üretim ortamına ait Dockerfile, CMD içerisinde zaten --reload değerini barındırır, dolayısıyla komutu her iki durumda da geçersiz kılarsınız.
  • Yayınlanan portlar "8888:8000", "8432:5432" ve "3000:3000" şeklindedir. Önünde bir adres belirtilmeyen yayınlanmış port, 0.0.0.0 adresine bağlanır; bu nedenle Postgres, yığın başladığı anda 8432 portu üzerinden genel internete yanıt verir.

Son madde ayrı bir uyarıyı hak etmektedir. Docker, kendi kurallarını ufw tarafından yönetilen zincirin önüne yazarak port yayınlar; bu nedenle ufw deny 8432 komutu, yayınlanmış bir container portunu kapatmaz. Docker'ın ufw kurallarını atlayarak port yayınlaması başlıklı yazı, bu süreçteki kuralları detaylandırmaktadır.

Gerçek bir sunucu için compose dosyası

server/ içinde çalışın, init-db.sh öğesini olduğu yerde tutun ve docker-compose.yaml kısmını bununla değiştirin.

name: mem0

services:
  mem0:
    build:
      context: .
      dockerfile: Dockerfile
    restart: unless-stopped
    env_file: .env
    ports:
      - "127.0.0.1:8888:8000"
    networks: [mem0_network]
    volumes:
      - mem0_history:/app/history
    depends_on:
      postgres:
        condition: service_healthy
    command: >
      sh -c "alembic upgrade head &&
             uvicorn main:app --host 0.0.0.0 --port 8000"
    environment:
      - PYTHONUNBUFFERED=1
      - DASHBOARD_URL=https://mem0.example.com
      - APP_DB_NAME=mem0_app
      - AUTH_DISABLED=false
      - MEM0_TELEMETRY=false

  postgres:
    image: pgvector/pgvector:pg17
    restart: unless-stopped
    shm_size: "128mb"
    networks: [mem0_network]
    environment:
      - POSTGRES_USER=${POSTGRES_USER:-postgres}
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD in .env}
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -q -U ${POSTGRES_USER:-postgres}"]
      interval: 5s
      timeout: 5s
      retries: 5
    volumes:
      - postgres_db:/var/lib/postgresql/data
      - ./init-db.sh:/docker-entrypoint-initdb.d/init-db.sh

  mem0-dashboard:
    build: ./dashboard
    restart: unless-stopped
    ports:
      - "127.0.0.1:3000:3000"
    networks: [mem0_network]
    environment:
      - NEXT_PUBLIC_API_URL=https://mem0.example.com
      - API_INTERNAL_URL=http://mem0:8000
    depends_on:
      mem0:
        condition: service_started

volumes:
  postgres_db:
  mem0_history:

networks:
  mem0_network:
    driver: bridge

Burada beş değişiklik önemlidir ve her birinin bir nedeni vardır.

Her ports girdisi 127.0.0.1 ile başlar, böylece çekirdek bu bağlantıları yalnızca sunucunun kendisinden kabul eder. Dışarıdan gelen her şey, sertifikayı tutan tek bileşen olan reverse proxy üzerinden ulaşır.

Postgres'in hiçbir ports bloğu yoktur. mem0 container'ı ona mem0_network üzerinden servis adıyla ulaşır, bu nedenle 8432 portunu dışarı açmak size bir şey kazandırmaz, aksine açık bir port maliyeti getirir. Bir kabuğa ihtiyacınız olduğunda docker compose exec postgres psql -U postgres kullanın.

Geçmiş verisi ./history bind mount konumundan adlandırılmış bir volume'e taşınır. Bind mount, veriyi bu ana makinedeki tek bir yola ve tek bir uid değerine bağlarken, adlandırılmış volume Docker'ın snapshot alabileceği ve taşıyabileceği bir nesnedir. Adlandırılmış volume'ler ve bind mount'lar hangisinin ne zaman doğru olduğunu açıklar.

Komut --reload öğesini çıkarır ve alembic upgrade head öğesini tutar. Bu migration adımını koruyun. Bu adım olmadan uygulama, tabloları olmayan bir veritabanına karşı başlar ve her istek ilk sorguda başarısız olur.

NEXT_PUBLIC_API_URL, tarayıcınızın çağırdığı URL'dir, bu nedenle http://mem0:8000 değil, herkese açık HTTPS adresi olmalıdır. Next.js her NEXT_PUBLIC_ değerini derleme zamanında içine gömer (inline), bu nedenle onu değiştirmek docker compose up -d --build mem0-dashboard gerektirir. Basit bir yeniden başlatma, eski değeri JavaScript içine gömülü tutar ve dashboard yanlış ana makineyi çağırır.

Gizli bilgiler .env dosyasında tutulur ve .env dosyası internete kapalı kalmalıdır

cd server
cp .env.example .env
openssl rand -hex 32    # paste into JWT_SECRET
openssl rand -hex 32    # paste into ADMIN_API_KEY
chmod 600 .env

POSTGRES_PASSWORD, JWT_SECRET ve ADMIN_API_KEY ayarlarını yapılandırın. AUTH_DISABLED=false değerini olduğu gibi bırakın. Bayrağın ismi, yaptığı işi açıkça ifade eder: bu özellik açıkken sunucu, porta erişebilen herkese belleğindeki tüm verileri sunar. Onboarding etkinliğinin yukarı yöne (upstream) gönderilmesini istemiyorsanız MEM0_TELEMETRY=false ayarını yapılandırın.

ADMIN_API_KEY, secrets.compare_digest kullanılarak X-API-Key başlığı ile karşılaştırılır ve bir eşleşme durumunda tüm veritabanı sorguları atlanır. Bu, tüm API için bir root kimlik bilgisidir. Buna uygun davranın: shell geçmişine kaydetmeyin, git sistemine eklemeyin ve herhangi bir komut satırı istemine yapıştırmayın. Compose env dosyaları ve gizli bilgilerin sızdığı noktalar ve API anahtarlarını bir ajanın bağlamından uzak tutmak başlıklı rehberlerin her ikisi de doğrudan geçerlidir, çünkü bu sunucunun çağırıcıları ajanlardır.

env_file dosyasından yüklenen değerler container ortamında tutulur ve docker inspect komutu bunları tam olarak yazdırır. docker grubundaki herkes bu değerleri okuyabilir ve docker grubundaki herkes, ana makine üzerinde root yetkisine sahip sayılır.

8888 portunu açmak yerine API önüne TLS yerleştirin

API 127.0.0.1:8888 adresinde, dashboard ise 127.0.0.1:3000 adresinde yanıt verir. nginx, 443 numaralı portta TLS (transport layer security) sonlandırmasını gerçekleştirir ve trafiği her iki servise de yönlendirir.

server {
    listen 443 ssl;
    server_name mem0.example.com;

    ssl_certificate     /etc/letsencrypt/live/mem0.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/mem0.example.com/privkey.pem;

    location ~ ^/(memories|search|configure|auth|api-keys|docs|openapi.json) {
        proxy_pass http://127.0.0.1:8888;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_read_timeout 180s;
    }

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

proxy_read_timeout göründüğünden daha önemlidir. Bir ekleme (add) çağrısı, dil modeli konuşmayı okuyup gerçekleri çıkarana kadar engellenir (block). CPU üzerinde çalışan yerel bir 8B model, genellikle nginx'in 60 saniyelik varsayılan süresinden daha uzun sürer; bu durumda model hala çalışmaya ve bellek yazılmaya devam ederken çağrıyı yapan taraf 504 Gateway Time-out hatası alır. Sonuç olarak, başarısız olduğu bildirilen bir bellek kaydıyla karşılaşırsınız.

varsayılan bir deny ufw politikası ile geri kalan portları kapatın ve yalnızca 22 ile 443 numaralı portları açık bırakın. Sertifikayı nginx arkasında Ubuntu 24.04 üzerinde certbot kullanarak oluşturun. Eğer sunucu halihazırda birden fazla Compose uygulamasını yönlendiren Traefik ile diğer uygulamalara hizmet veriyorsa, ikinci bir proxy kurmak yerine mem0'ı mevcut yönlendiriciye ekleyin.

Duman testi: bir bellek ekleyin ve geri okuyun

export MEM0_KEY='<the ADMIN_API_KEY from .env>'

curl -sS -X POST http://127.0.0.1:8888/memories \
  -H "Content-Type: application/json" \
  -H "X-API-Key: $MEM0_KEY" \
  -d '{"messages":[{"role":"user","content":"I deploy with Docker Compose and I run Postgres 17."}],"user_id":"smoke"}'

Sağlıklı bir yanıt, bir results listesi içeren JSON nesnesidir; her girdi bir id, ayıklanan memory metni ve "event": "ADD" değerini tutar. Mevcut algoritma yalnızca ADD olaylarını döndürür. UPDATE ve DELETE olayları kaldırılmıştır, bu nedenle bunların yokluğu bir hata değildir.

curl -sS -X POST http://127.0.0.1:8888/search \
  -H "Content-Type: application/json" \
  -H "X-API-Key: $MEM0_KEY" \
  -d '{"query":"which database do I run?","filters":{"user_id":"smoke"},"top_k":5}'

Postgres 17 hakkındaki bilgi, bir puan ile geri dönmelidir. Tanımlayıcıyı, gösterildiği gibi filters içine geçirin. Üst düzey bir user_id hala çalışır ve sunucu, her kullandığınızda Top-level user_id in /search is deprecated. Use filters={...} instead. kaydını tutar.

Test verilerinin gerçek aramaları kirletmemesi için temizlik yapın:

curl -sS -X DELETE "http://127.0.0.1:8888/memories?user_id=smoke" \
  -H "X-API-Key: $MEM0_KEY"

Arama beklediğinizden daha az satır döndürürse, geri getirme (retrieval) işlemini suçlamadan önce varsayılan değerleri kontrol edin. Mevcut sürümde top_k varsayılan olarak 100 yerine 20'dir ve threshold değeri yok yerine 0.1 olarak ayarlanmıştır; bu nedenle zayıf eşleşmeler artık sizin için filtrelenmektedir. Bu işlem curl üzerinden çalıştığında, aynı uç noktaları doğrudan veya aynı VPS üzerinde çalışan bir MCP sunucusu aracılığıyla bir aracıya (agent) bağlayabilirsiniz.

mem0'ı hiç OpenAI anahtarı olmadan çalıştırmak

İlk beş dakika içinde karşılaşacağınız engel ile başlayın. Sunucu imajı, sabit bir sağlayıcı kütüphanesi setiyle gelir ve /configure bunların dışındaki her şeyi reddeder:

LLM provider 'ollama' is not bundled in this image. Bundled providers: openai, anthropic, gemini. To use another provider, install its Python package, rebuild the container, and extend BUNDLED_LLM_PROVIDERS in server/main.py.

Hiçbir şeyi yeniden derlemeniz gerekmez. Ollama, /v1 adresinde OpenAI uyumlu bir API sunar; bu API /v1/chat/completions ve /v1/embeddings kapsamını karşılar ve mem0'ın openai sağlayıcısı bir openai_base_url kabul eder. Bu anahtarı Ollama'ya yönlendirin; sağlayıcı aslında openai olduğu için paketlenmiş kontrol başarılı olacaktır. Yalnızca adres değişir.

Ollama'yı aynı Compose projesine ekleyin:

  ollama:
    image: ollama/ollama
    restart: unless-stopped
    networks: [mem0_network]
    ports:
      - "127.0.0.1:11434:11434"
    volumes:
      - ollama_models:/root/.ollama

En üst düzey volumes: anahtarının altına ollama_models: ekleyin, ardından bir sohbet modeli ve bir yerleştirme (embedding) modeli çekin:

docker compose up -d ollama
docker compose exec ollama ollama pull llama3.1:8b
docker compose exec ollama ollama pull nomic-embed-text

Ollama ana makinede Ollama'nın doğrudan VPS üzerinde çalıştırılması bölümünde olduğu gibi bir systemd birimi olarak zaten çalışıyorsa, konteyneri 127.0.0.1:11434 adresine yönlendirmeyin. mem0 konteynerinin içinde 127.0.0.1, mem0 konteynerinin kendisidir. mem0 servisine extra_hosts: ["host.docker.internal:host-gateway"] verin, Ollama'nın köprü ağının erişebileceği bir adreste dinleme yapması için bir systemd drop-in dosyasında Environment="OLLAMA_HOST=0.0.0.0:11434" ayarını yapın ve 11434 numaralı portu güvenlik duvarında kapalı tutun.

Herhangi bir yapılandırma yapmadan önce modele yerleştirme boyutunu sorun

Bu tek adım, geri getirmenin (retrieval) çalışıp çalışmayacağını belirler.

mem0'ın pgvector deposu, tablosunu sabit bir vektör genişliği olan vector vector(1536) ile oluşturur; çünkü embedding_model_dims varsayılan olarak OpenAI'ın text-embedding-3-small genişliği olan 1536 değerini kullanır. nomic-embed-text ise 768 değer döndürür. mem0 içinde bu iki sayıyı karşılayan bir mekanizma yoktur, bu nedenle uyumsuzluk ilk ekleme işleminde Postgres'ten gelen bir hata ile ortaya çıkar:

expected 1536 dimensions, not 768

Bu paragraftaki sayıya da güvenmeyin. Modele sorun:

curl -sS http://127.0.0.1:11434/v1/embeddings \
  -H "Content-Type: application/json" \
  -d '{"model":"nomic-embed-text","input":"dimension check"}' \
  | python3 -c "import json,sys; print(len(json.load(sys.stdin)['data'][0]['embedding']))"

Bu komut, koleksiyonunuzun kullanması gereken genişliği yazdırır. Yapılandırmayı bir dosyaya yazın; çünkü bir Postgres parolasını kabuk tırnakları üzerinden yapıştırmak, üretim ortamında yazım hatalarına yol açar.

{
  "vector_store": {
    "provider": "pgvector",
    "config": {
      "host": "postgres",
      "port": 5432,
      "dbname": "postgres",
      "user": "postgres",
      "password": "<POSTGRES_PASSWORD from .env>",
      "collection_name": "memories_local_768",
      "embedding_model_dims": 768
    }
  },
  "llm": {
    "provider": "openai",
    "config": {
      "model": "llama3.1:8b",
      "api_key": "ollama",
      "openai_base_url": "http://ollama:11434/v1",
      "temperature": 0.2
    }
  },
  "embedder": {
    "provider": "openai",
    "config": {
      "model": "nomic-embed-text",
      "api_key": "ollama",
      "openai_base_url": "http://ollama:11434/v1"
    }
  }
}
curl -sS -X POST http://127.0.0.1:8888/configure \
  -H "Content-Type: application/json" \
  -H "X-API-Key: $MEM0_KEY" \
  -d @config.json

curl -sS http://127.0.0.1:8888/configure -H "X-API-Key: $MEM0_KEY"

İkinci çağrı yapılandırmayı geri okur; bu, yazma işleminin başarılı olduğunu doğrulayan kontroldür. Ardından yukarıdaki duman testini tekrarlayın.

Bu JSON içindeki dört detay bariz değildir ve yanlış yapıldığında her biri bir şeyleri bozar.

api_key, ollama dizgisidir ve Ollama bu değeri görmezden gelir. Boş olamaz, çünkü OpenAI istemci kütüphanesi hiçbir anahtar ayarlanmadığında süreçten herhangi bir istek çıkmadan önce hata verir. Boş olmayan herhangi bir dizgi çalışır.

embedding_model_dims, vektör deposu üzerinde kullanılır ve yerleştirici (embedder) üzerinde kasten embedding_dims yoktur. mem0, OpenAI dimensions parametresini yalnızca embedding_dims ayarlandığında gönderir ve Matryoshka kırpma işlemini uygulamayan arka uçlar bu parametreyi doğrudan reddeder. Genişliği tablonun oluşturulduğu yerde ayarlayın ve yerleştiriciyi olduğu gibi bırakın.

collection_name yenidir. mem0 tablosunu CREATE TABLE IF NOT EXISTS ile oluşturur, bu nedenle mevcut bir koleksiyona farklı bir genişlik yönlendirmek hiçbir işe yaramaz: eski vector(1536) sütunu kalır ve her ekleme işlemi başarısız olur. Genişlik değişikliği için yeni bir koleksiyon adı gerekir veya eski tabloyu elle silmeniz gerekir.

openai_base_url içindeki ana makine, localhost değil, Compose servis adı olan ollama'dir. Konteynerler, paylaşılan ağları üzerinde birbirlerini servis adlarıyla çözerler.

Tamamen yerel yolun maliyeti

Kalite konusunda kendinize karşı dürüst olun. mem0'ın yayınlanan kıyaslama puanları, çıkarım işlemini yapan öncü modellerle ölçülmüştür; bu yüzden bunları VPS üzerindeki 8B'lik bir model için bir tahmin değil, bir tavan değeri olarak görün. Küçük bir model daha belirsiz gerçekler yazar ve bazen JSON istendiğinde düzyazı döndürür; bu durum, ekleme çağrısının hata vermeden boş bir results listesi döndürmesiyle kendini gösterir.

Hız diğer maliyettir. Yalnızca CPU ile çıkarım yapmak, her ekleme çağrısı için saniyeler sürer ve depoladığınız her mesaj bu maliyeti öder. İstenen JSON'ın dışına çıkan bir model bu durumu daha da kötüleştirir, bu nedenle yanıtın num_predict ile sınırlandırılması, herhangi bir ekleme çağrısının ne kadar sürebileceğine bir tavan koyar. Eğer bu gecikme önemliyse, GPU takılı bir VPS dürüst çözümdür. 8B'lik bir modele daha fazla CPU çekirdeği vermek, insanların beklediğinden çok daha az yardımcı olur. Modeli değiştirmek, makineyi değiştirmekten daha ucuz bir kaldıraçtır ve VPS üzerinde Nemotron 3.5 Lightning, çekmeniz gereken etiketi, ihtiyaç duyduğu RAM miktarını ve yalnızca CPU ile çalışmanın yaşanabilir olup olmadığını size sunar.

Ne seçerseniz seçin tek bir kural geçerlidir: aynı koleksiyon içinde asla farklı yerleştirme modellerini karıştırmayın. Tesadüfen aynı genişliğe sahip iki farklı model, karşılaştırılamaz vektörler üretir. Ekleme başarılı olur, arama satırları döndürür ancak satırlar yanlıştır ve hiçbir yerde bir hata rapor edilmez.

Yedeklemeler: tek değil, iki veritabanı var

En yaygın mem0 yedekleme hatası, yalnızca tek bir veritabanının dışa aktarılmasıdır. init-db.sh, varsayılan postgres veritabanının yanında mem0_app veritabanını oluşturur ve bu veritabanları farklı veriler içerir. postgres veritabanında anıların tutulduğu pgvector koleksiyonları bulunur. mem0_app ise kullanıcıları, oturumları, API anahtarlarını ve istek günlüklerini içerir. Her self-hosted uygulama durum verilerini kendine özgü biçimde ayırır. Bu nedenle aynı işi yapan iki fotoğraf sunucusu için bile farklı yedekleme komutları gerekir. Bir dump dosyasına güvenmeden önce uygulamanızın hangi verileri depoladığını inceleyin. Bu yelpazenin diğer ucunda, 90'lar video mağazası olarak yeniden oluşturulan bir Jellyfin kitaplığı gibi bir yapı bulunur. Bu yapı tüm kataloğunu başka bir servisten okur. Bu nedenle kendi yapılandırmasının kopyalanması genellikle yeterlidir. mem0 için ise her iki veritabanının da yedeklenmesi gerekir; aksi halde geri yükleme kullanılamaz.

Yalnızca postgres yedeğini geri yüklerseniz bellekler geri gelir ancak tüm hesaplar ve API anahtarları kaybolur; bu durumda hiçbir şey kimlik doğrulaması yapamaz ve bellekleri okuyamaz. Her ikisini ve rolleri tek komutla yedekleyin:

docker compose exec -T postgres pg_dumpall -U postgres --clean \
  | gzip > "mem0-$(date +%F).sql.gz"

Geçmiş (history) birimi Postgres'ten ayrıdır ve kendi kopyasına ihtiyaç duyar:

docker run --rm -v mem0_mem0_history:/data -v "$PWD:/backup" \
  alpine tar czf /backup/mem0-history.tgz -C /data .

Docker, birim adlarının başına proje adını ekler; bu nedenle mem0_mem0_history varsayımında bulunmadan önce docker volume ls ile kendi adlarınızı doğrulayın.

Yedeği boş bir container içine geri yükleyin ve herhangi bir veriye güvenmeden önce satır sayılarını kontrol edin:

gunzip -c mem0-2026-08-03.sql.gz \
  | docker compose exec -T postgres psql -U postgres -d postgres

Daha önce geri yüklemediğiniz bir yedek, sadece bir tahmindir. Yedekler doğru alındıktan sonra, bunları restic ile uzak depolama alanına snapshot göndererek sunucudan dışarı aktarın; çünkü koruduğu sunucuda barınan bir yedek, hiçbir şeyi korumaz.

Hata modları ve karşılaşacağınız kesin dizgeler

{"detail":"Authentication required. Provide a Bearer token or X-API-Key header."} ifadesi, başlığın eksik veya yanlış yazılmış olduğu anlamına gelir. İsim X-API-Key şeklindedir ve curl, başlık isimlerini olduğu gibi gönderir.

Bir ekleme işleminde {"detail":"At least one identifier (user_id, agent_id, run_id) is required."} hatası, istekte bunlardan hiçbirinin bulunmadığını belirtir. Arama filtreleri tam olarak bu alanlar üzerinde çalıştığı için, bir bellek mutlaka bir kapsam dahilinde olmalıdır.

HTTP 400 ile birlikte alınan LLM provider 'ollama' is not bundled in this image, "provider": "ollama" gönderdiğiniz anlamına gelir. Ollama'ya yönlendirilmiş openai_base_url ile "provider": "openai" kullanın.

Postgres'ten gelen expected 1536 dimensions, not 768, koleksiyonun bir genişlikte oluşturulduğunu ancak gömücünün (embedder) başka bir genişlik döndürdüğünü belirtir. Vektör deposunda embedding_model_dims ayarını yapın ve yeni bir collection_name kullanın.

Arama, model değişikliğinden sonra anlamsız satırlar döndürür ve hiçbir yerde hata oluşmaz. Genişlik hala eşleştiği için veritabanı çalışmaya devam eder, ancak iki farklı model aynı cümleyi farklı konumlara yerleştirir. Yeni bir koleksiyon başlatın ve verileri tekrar ekleyin.

Ollama'ya erişirken mem0 günlüklerinde görülen Connection refused, genellikle openai_base_url içindeki 127.0.0.1 anlamına gelir. Container içinde bu adres, container'ın kendisidir. Servis ismini kullanın veya Ollama ana makinede (host) çalışıyorsa host gateway adresini tercih edin.

Bir ekleme işleminde nginx'ten gelen 504 Gateway Time-out, modelin proxy_read_timeout süresinden daha uzun sürdüğü anlamına gelir. Bu değeri artırın ve isteği yeniden denemeden önce belleğin zaten yazılıp yazılmadığını kontrol edin.

docker compose up --build sırasında oluşan exit code 137, dashboard derlemesini durduran bellek yetersizliği (OOM killer) hatasıdır. Swap alanı ekleyin veya imajı daha büyük bir makinede derleyip bir kayıt defterine (registry) gönderin.

error: port 3000 is already in use, 3000 veya 8888 numaralı portlar kullanımdayken başlatılmayı reddeden deponun make up hedefinden kaynaklanır. lsof -iTCP:3000 -sTCP:LISTEN komutu ile portu kullanan süreci bulun.

FAQ

Grafik bellekli mem0 çalıştırmak için hala Neo4j gerekiyor mu?

Hayır. Nisan 2026'da yayınlanan yeni bellek algoritması, açık kaynaklı SDK içerisinden graph_store ve enable_graph yapılandırma anahtarlarını kaldırdı. Varlık çıkarımı artık normal bir ekleme işlemi sırasında çalışır ve <collection_name>_entities adlı ikinci bir pgvector koleksiyonuna yazılır; bu nedenle harici bir grafik veritabanına, fazladan bir container'a veya taşıma adımına gerek yoktur. Bunun karşılığında, arama sonuçlarındaki relations alanı artık mevcut değildir. Varlıklar artık üzerinde gezinebileceğiniz kenarlar (edges) sağlamak yerine bir belleğin sıralama puanını yükseltir; bu nedenle bu ilişkiler üzerinde gezinen bir uygulamanın mem0 dışında kendi grafik deposuna ihtiyacı vardır.

Kendi kendine barındırılan (self-hosted) bir mem0 sunucusunu çalıştırabilecek en küçük VPS nedir?

Dil modeli başka bir yerde barındırılıyorsa, API container'ı, Postgres ve kontrol paneli için 2 GB RAM ve yaklaşık 4 GB boş disk alanı yeterlidir. En kritik an ilk derleme aşamasıdır; çünkü Next.js kontrol panelini derlemek, çalıştırmaktan daha fazla bellek tüketir ve 1 GB'lık bir sunucuda derleme işlemi exit code 137 hatasıyla sonlandırılır. Eğer Ollama aynı sunucuda çalışacaksa, modeli de hesaba katın: 8B boyutunda ve 4-bit kuantize edilmiş bir model tek başına yaklaşık 6 GB bellek gerektirir, bu nedenle 8 GB RAM planlayın.

mem0'ı OpenAI API anahtarı olmadan çalıştırabilir miyim?

Evet, Ollama'nın OpenAI uyumlu uç noktası aracılığıyla çalıştırabilirsiniz. "provider": "ollama" ayarını boş bırakmak başarısız olur, çünkü sunucu imajı yalnızca openai, anthropic ve gemini kütüphanelerini içerir ve HTTP 400 hatası döndürür. Bunun yerine "provider": "openai" değerini koruyun ve hem llm hem de embedder için "openai_base_url": "http://ollama:11434/v1" ayarını boş olmayan herhangi bir api_key ile yapılandırın. Ollama anahtarı görmezden gelir ve paketlenmiş sağlayıcı kontrolü, sağlayıcı gerçekten openai olduğu için başarılı olur.

Yerel bir embedding modeline geçtikten sonra mem0 neden sonuç döndürmüyor?

Çünkü pgvector tablosu sabit bir genişlikte oluşturulmuştur. embedding_model_dims varsayılan olarak 1536 değerini kullanır, nomic-embed-text ise 768 döndürür ve Postgres ekleme işlemini expected 1536 dimensions, not 768 hatasıyla reddeder. mem0 tabloyu CREATE TABLE IF NOT EXISTS ile oluşturur, bu nedenle sadece sayıyı değiştirmek mevcut koleksiyon üzerinde bir etki yaratmaz. embedding_model_dims değerini modelinizin gerçek genişliğine ayarlayın, /v1/embeddings çağrısı yapıp dönen değerleri sayarak bu genişliği doğrulayın ve aynı zamanda vektör deposuna yeni bir collection_name atayın.