Storage

Storing Vectors

Insert and update vector embeddings with metadata using the JavaScript SDK or Postgres.


Once you've created a bucket and index, you can start storing vectors. Vectors can include optional metadata for filtering and enrichment during queries.

Basic vector insertion

1
import { } from '@supabase/supabase-js'
2
3
const = ('https://your-project.supabase.co', 'your-service-key')
4
5
// Get bucket and index
6
const = ...('embeddings')
7
const = .('documents-openai')
8
9
// Insert vectors
10
const { } = await .({
11
: [
12
{
13
: 'doc-1',
14
: {
15
: [0.1, 0.2, 0.3 /* ... rest of embedding ... */],
16
},
17
: {
18
: 'Getting Started with Vector Buckets',
19
: 'documentation',
20
},
21
},
22
{
23
: 'doc-2',
24
: {
25
: [0.4, 0.5, 0.6 /* ... rest of embedding ... */],
26
},
27
: {
28
: 'Advanced Vector Search',
29
: 'blog',
30
},
31
},
32
],
33
})
34
35
if () {
36
.('Error storing vectors:', )
37
} else {
38
.('✓ Vectors stored successfully')
39
}

Storing vectors from Embeddings API

Generate embeddings using an LLM API and store them directly:

1
import { } from '@supabase/supabase-js'
2
import from 'openai'
3
4
const = ('https://your-project.supabase.co', 'your-service-key')
5
6
const = new ({
7
: ..,
8
})
9
10
// Documents to embed and store
11
const = [
12
{ : '1', : 'How to Train Your AI', : 'Guide for training models...' },
13
{ : '2', : 'Vector Search Best Practices', : 'Tips for semantic search...' },
14
{
15
: '3',
16
: 'Building RAG Systems',
17
: 'Implementing retrieval-augmented generation...',
18
},
19
]
20
21
// Generate embeddings
22
const = await ..({
23
: 'text-embedding-3-small',
24
: .(() => .),
25
})
26
27
// Prepare vectors for storage
28
const = .((, ) => ({
29
: .,
30
: {
31
: .[].,
32
},
33
: {
34
: .,
35
: 'knowledge_base',
36
: new ().(),
37
},
38
}))
39
40
// Store vectors in batches (max 500 per request)
41
const = ...('embeddings')
42
const = .('documents-openai')
43
44
for (let = 0; < .; += 500) {
45
const = .(, + 500)
46
const { } = await .({ : })
47
48
if () {
49
.(`Error storing batch ${ / 500 + 1}:`, )
50
} else {
51
.(`✓ Stored batch ${ / 500 + 1} (${.} vectors)`)
52
}
53
}

Updating vectors

1
const index = bucket.index('documents-openai')
2
3
// Update a vector (same key)
4
const { error } = await index.putVectors({
5
vectors: [
6
{
7
key: 'doc-1',
8
data: {
9
float32: [0.15, 0.25, 0.35 /* ... updated embedding ... */],
10
},
11
metadata: {
12
title: 'Getting Started with Vector Buckets - Updated',
13
updated_at: new Date().toISOString(),
14
},
15
},
16
],
17
})
18
19
if (!error) {
20
console.log('✓ Vector updated successfully')
21
}

Deleting vectors

1
const index = bucket.index('documents-openai')
2
3
// Delete specific vectors
4
const { error } = await index.deleteVectors({
5
keys: ['doc-1', 'doc-2'],
6
})
7
8
if (!error) {
9
console.log('✓ Vectors deleted successfully')
10
}

Metadata best practices

Metadata makes vectors more useful by enabling filtering and context:

1
const vectors = [
2
{
3
key: 'product-001',
4
data: { float32: [...] },
5
metadata: {
6
product_id: 'prod-001',
7
category: 'electronics',
8
price: 299.99,
9
in_stock: true,
10
tags: ['laptop', 'portable'],
11
description: 'High-performance ultrabook'
12
}
13
},
14
{
15
key: 'product-002',
16
data: { float32: [...] },
17
metadata: {
18
product_id: 'prod-002',
19
category: 'electronics',
20
price: 99.99,
21
in_stock: true,
22
tags: ['headphones', 'wireless'],
23
description: 'Noise-cancelling wireless headphones'
24
}
25
}
26
]
27
28
const { error } = await index.putVectors({ vectors })

Metadata field guidelines

  • Keep it lightweight - Metadata is returned with query results, so large values increase response size
  • Use consistent types - Store the same field with consistent data types across vectors
  • Index key fields - Mark fields you'll filter by to improve query performance
  • Avoid nested objects - While supported, flat structures are easier to filter

Batch processing large datasets

For storing large numbers of vectors efficiently:

1
import { createClient } from '@supabase/supabase-js'
2
import fs from 'fs'
3
4
const supabase = createClient(...)
5
const index = supabase.storage.vectors
6
.from('embeddings')
7
.index('documents-openai')
8
9
// Read embeddings from file
10
const embeddingsFile = fs.readFileSync('embeddings.jsonl', 'utf-8')
11
const lines = embeddingsFile.split('\n').filter(line => line.trim())
12
13
const vectors = lines.map((line, idx) => {
14
const { key, embedding, metadata } = JSON.parse(line)
15
return {
16
key,
17
data: { float32: embedding },
18
metadata
19
}
20
})
21
22
// Process in batches
23
const BATCH_SIZE = 500
24
let processed = 0
25
26
for (let i = 0; i < vectors.length; i += BATCH_SIZE) {
27
const batch = vectors.slice(i, i + BATCH_SIZE)
28
29
try {
30
const { error } = await index.putVectors({ vectors: batch })
31
32
if (error) throw error
33
34
processed += batch.length
35
console.log(`Progress: ${processed}/${vectors.length}`)
36
} catch (error) {
37
console.error(`Batch failed at offset ${i}:`, error)
38
// Optionally implement retry logic
39
}
40
}
41
42
console.log('✓ All vectors stored successfully')

Performance optimization

Batch operations

Always use batch operations for better performance:

1
// ❌ Inefficient - Multiple requests
2
for (const vector of vectors) {
3
await index.putVectors({ vectors: [vector] })
4
}
5
6
// ✅ Efficient - Single batch operation
7
await index.putVectors({ vectors })

Metadata considerations

Keep metadata concise:

1
// ❌ Large metadata
2
metadata: {
3
full_document_text: 'Very long document content...',
4
detailed_analysis: { /* large object */ }
5
}
6
7
// ✅ Lean metadata
8
metadata: {
9
doc_id: 'doc-123',
10
category: 'news',
11
summary: 'Brief summary'
12
}

Next steps