DriversRecommendedOutdated drivers can make a good PC feel brokenScan driver issues before chasing fixes manually.Scan NowHalloween DealsAmazon USHalloween week deals: useful picks before month-endAmazon US: current deals, useful picks and tech finds.Check DealsClean PCRecommendedOne scan can reveal what keeps slowing WindowsLook for cleanup and repair opportunities.Run Scan×
Skip to content
VGSources
Blog

How to Run CRUD Operations in Elasticsearch Safely

A practical Elasticsearch CRUD guide covering Index, Get, Update, Delete, Bulk NDJSON, refresh timing, conflict protection with sequence numbers and primary terms, data streams, and least-privilege permissions.
WorldElasticsearch Safely Length10 min Posted Quest giverVGSources Team
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Elasticsearch CRUD is a small set of HTTP operations on JSON documents: index (create or replace), get (read), update (change selected fields), and delete (remove). Use PUT /index/_doc/id when your application owns the ID, POST /index/_doc when Elasticsearch should generate one, _update for partial changes, and conditional parameters when a stale read must not overwrite a newer write. The procedures below cover single-document requests, bulk NDJSON, refresh behavior, data streams, permissions, and failure handling.

The document model and a safe starting point

An Elasticsearch application stores JSON documents inside indices. A document has an index, an identifier, and a JSON source. The document APIs include Index, Get, Delete, Update, Bulk, Multi-get, Update-by-query, and Delete-by-query. CRUD becomes predictable when you decide three things before writing data:

As an Amazon Associate I earn from qualifying purchases.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  • Identity: choose a stable application ID or let Elasticsearch generate one.
  • Write semantics: choose create-only, complete replacement, or a partial/scripted update.
  • Concurrency policy: decide whether an unconditional write is acceptable or whether the last read’s sequence number and primary term must be checked.

Define mappings and choose those IDs before loading production data. A mapping change made after documents exist can require a separate migration, so treating the index design as part of the write workflow avoids accidental type conflicts.

Create documents with the Index API

Use an explicit ID with PUT

When the application already has a durable identifier, put the document at that identifier:

#1 Best Overall
PUT /products/_doc/42
Content-Type: application/json

{"name":"Keyboard","price":99.0}

The request creates document 42 in products. If that ID already exists, the Index API replaces the document source and increments its version; it is therefore an overwrite-style operation, not create-only. Send the complete replacement source when replacement is intended.

Let Elasticsearch generate an ID with POST

POST /products/_doc
Content-Type: application/json

{"name":"Keyboard","price":99.0}

Use this form when the caller does not own the identifier. The generated ID must be captured from the response if another part of the application will later read, update, or delete that document.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Prevent replacement when an ID already exists

For create-only behavior, add op_type=create to the request or use a create action in a bulk request. If the identifier is already present, the create operation fails with a conflict instead of replacing the existing source. This is the correct choice for idempotent imports where an existing record should be investigated rather than silently overwritten.

PUT /products/_doc/42?op_type=create
Content-Type: application/json

{"name":"Keyboard","price":99.0}

Choose replacement versus update deliberately

Intent API form What happens to fields not sent Version/no-op behavior
Create or replace the complete document PUT /products/_doc/42 They disappear because the supplied source is the replacement source. A new version is created even when the source is unchanged.
Create only PUT ...?op_type=create or bulk create The existing document is not replaced. An existing ID causes a conflict.
Change selected fields POST /products/_update/42 Unmentioned fields remain. Use detect_noop when avoiding a write for an unchanged partial update matters.

Read documents and account for refresh

Get one document by ID

GET /products/_doc/42

The response tells you whether the document was found and, when available, includes its _source. Use this endpoint when the identifier is known and you need the stored document rather than a search result.

Read several known IDs

Use the multi-get API for a set of known identifiers instead of issuing unrelated single-document requests. The request can specify the index once and list the IDs to retrieve:

GET /products/_mget
Content-Type: application/json

{"ids":["42","43","44"]}

Handle each returned item independently: a missing ID is a valid per-document outcome even when other IDs were found.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Do not confuse a write with search visibility

Search visibility is governed by refresh behavior. A workflow that must search for a just-written document can request an explicit refresh, but doing so on every write adds write overhead. If immediate search visibility is not required, allow normal refresh scheduling. A direct document get and a search-after-write check are different workflow requirements; choose refresh behavior for the latter rather than reflexively refreshing every request.

Update without losing unrelated fields

Apply a partial document change

The Update API accepts a partial doc object. Existing fields not included in that object remain in the document:

POST /products/_update/42
Content-Type: application/json

{"doc":{"price":89.0}}

This is safer than sending a shortened source through the Index API when the application intends to change only one property.

Use Painless for an atomic transformation

When the new value depends on the current value, send a Painless script and parameters. The following decrements stock in the update operation:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
POST /products/_update/42
Content-Type: application/json

{"script":{"source":"ctx._source.stock -= params.n","params":{"n":1}}}

Keep the transformation in the script rather than performing a read, calculating a value in application code, and issuing an unconditional replacement. That read-modify-write pattern is vulnerable to a concurrent writer unless you add optimistic concurrency controls.

Use upsert behavior when a document may be absent

Update requests can include an upsert document for the not-found case. Bulk update actions support doc, script, upsert, and doc_as_upsert. Choose one intentionally: an upsert creates a defined initial document, while doc_as_upsert uses the partial document as that initial source.

Know when Index is still the right update

If the application has a complete authoritative representation, sending that complete source through Index is straightforward and deterministic. It always creates a new version, including when the source has not changed. If avoiding a needless write is important, use Update with no-op detection rather than relying on Index to detect identical content.

Delete one document or delete by criteria

Delete a known ID

DELETE /products/_doc/42

This removes one known document. Treat the response as an operation result and record failures for retry or investigation.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Delete documents matching a query

For criteria-based removal, use Delete by query. Start with the equivalent search query and inspect a small sample before executing the destructive request. For example, if a mapping has a boolean discontinued field:

POST /products/_delete_by_query
Content-Type: application/json

{"query":{"term":{"discontinued":true}}}

Replace the example field with the actual field and value in your index. A broad query can remove far more data than intended, so verify the index target, filter, and expected match set before running it.

Process many CRUD actions with Bulk NDJSON

Build the two-line action format

Bulk requests use newline-delimited JSON (NDJSON). Each index, create, or update action has an action line followed by a source or update line. A delete action has no following source line:

POST /_bulk
Content-Type: application/x-ndjson

{"index":{"_index":"products","_id":"1"}}
{"name":"Mouse","price":25}
{"update":{"_index":"products","_id":"1"}}
{"doc":{"price":20}}
{"delete":{"_index":"products","_id":"2"}}

Bulk supports index, create, update, and delete. It reduces request overhead for independent operations, but it does not make every item succeed or fail as one transaction.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Preserve line boundaries with curl

Store the NDJSON payload in a file with a final newline and send it with --data-binary:

curl -X POST "http://localhost:9200/_bulk" 
  -H "Content-Type: application/x-ndjson" 
  --data-binary @bulk.ndjson

Using a mode that rewrites newlines can corrupt the action/source pairing. Keep each action on its own line and do not add commas or array brackets.

Inspect every item result

The bulk response contains a per-item result array. Parse that array and handle each action independently: one failed create, update, or delete does not imply that neighboring actions failed. Record the item identifier, operation, and error, then retry only operations that are safe to retry. A bulk create conflict, for example, should not be retried as an unconditional index because that would change the intended create-only semantics.

Protect read-modify-write flows with optimistic concurrency

Why an unconditional write can be stale

Suppose client A reads document 42, client B changes its price, and client A later writes the old complete source. Without a condition, A can overwrite B’s newer change. Elasticsearch assigns a sequence number and primary term to document operations so a client can prove that its write is based on the version it last read.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Send the last sequence number and primary term

Take _seq_no and _primary_term from the last read, then include them in the write:

PUT /products/_doc/42?if_seq_no=7&if_primary_term=3
Content-Type: application/json

{"name":"Keyboard","price":89.0}

If another operation changed the document, the condition no longer matches. Elasticsearch returns HTTP 409 and does not apply the stale write. The application should fetch the current document, merge or reject the user’s change according to business rules, and then retry with the newly observed concurrency values if appropriate.

Apply concurrency controls to bulk operations

Bulk index and delete actions can carry the same sequence-number and primary-term conditions. Bulk update also supports retry_on_conflict for bounded retries. Use a small, deliberate retry limit and still inspect the final per-item result; retries are not a substitute for resolving a conflicting business edit.

Special case: documents in data streams

The normal indexing API cannot update an existing document in a data stream. To update or delete a data-stream document, target the backing index that contains that document. Identify the backing index as part of your operational workflow, and ensure the account has permission to address it. A request aimed only at the data-stream name is not a general replacement for a backing-index update or delete.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Permissions and automatic index creation

With security enabled, grant only the privileges required by the operation and target index:

Operation Privileges that can be required
Index a document create, index, or write
Create-only request create_doc can be required
Delete a document delete or write
Update a document index or write
Automatic index creation auto_configure, create_index, or manage, according to the security configuration

Permission failures can look like CRUD bugs when the endpoint and JSON are correct. Check the authenticated principal’s privilege on the concrete index, including a data stream’s backing index, before changing the request body.

A practical CRUD workflow

  1. Design first: define mappings and select stable IDs for every entity.
  2. Choose the write contract: use create-only for immutable imports, Index for complete replacement, or Update for partial and scripted changes.
  3. Create or index: use explicit IDs when the application owns identity; otherwise capture generated IDs from POST responses.
  4. Read deliberately: use Get or multi-get for known IDs and decide whether a search immediately after writing truly needs an explicit refresh.
  5. Update safely: use doc, scripts, or upsert forms; use sequence-number and primary-term conditions for read-modify-write operations.
  6. Delete narrowly: verify a query against a sample before Delete by query, and use a direct ID delete when the target is known.
  7. Batch independent work: send valid NDJSON with --data-binary, then inspect every item result rather than trusting the HTTP-level response alone.
  8. Handle conflicts and permissions: treat HTTP 409 as a stale-write signal, and verify least-privilege access for the operation and target index.

Common failure modes and fixes

An existing document was unexpectedly replaced

The request used Index without op_type=create. Switch to create-only semantics when replacement is not allowed, or use Update if the intent was to change selected fields.

A field disappeared after an update

A complete source was sent through Index even though the caller supplied only a subset of fields. Resend the authoritative complete document, or use Update with a partial doc for future changes.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

A search cannot find a document just written

The write may not yet be visible to search because refresh is not immediate. Request an explicit refresh only for workflows that require immediate search visibility; otherwise wait for normal refresh scheduling.

A bulk request reports mixed results

Bulk actions are independent. Parse the per-item result array, preserve each error and ID, and retry only the failed actions with the same intended semantics.

A write returns HTTP 409

The supplied sequence-number and primary-term condition is stale, or a create-only request encountered an existing ID. For optimistic concurrency, read the current document and resolve the merge; for create-only conflicts, decide whether the duplicate is expected and avoid silently converting the operation into replacement.

An update or delete against a data stream fails

Target the backing index that stores the document. The ordinary indexing API is not an update path for an existing data-stream document.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The endpoint is correct but authorization fails

Check the principal’s index privileges: updates need index or write, deletes need delete or write, and create-only requests can need create_doc. If the index does not yet exist, verify the configured automatic-index-creation privilege as well.

Quick Recap

Choosing the right CRUD approach

Situation Recommended approach Main trade-off
One known document, complete authoritative state Index with an explicit ID Simple replacement, but omitted fields are removed and unchanged sources still create a new version.
One known document, only a few fields change Update with doc Preserves other fields; use no-op detection when avoiding unchanged writes matters.
Value depends on current state Scripted Update Performs the transformation in Elasticsearch; concurrency conditions may still be needed for business-level conflict handling.
Many independent operations Bulk NDJSON Lower request overhead, but every item must be checked because outcomes can be mixed.
Search must immediately see a write Explicit refresh for that workflow Improves visibility timing at the cost of additional write overhead.
Stale reads must never overwrite newer data if_seq_no and if_primary_term Conflicts become HTTP 409 responses that the application must resolve.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Leave a Reply

Your email address will not be published. Required fields are marked *

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More quests from Patch Notes

  1. How to Set Up a RedM (RDR2) Server in 2026: License Key, txAdmin and server.cfg, Step by StepBlog11min
  2. Best RedM (RDR2) Server Hosting in 2026: Comparing Four Hosts on Slots, Memory and PriceBlog10min
  3. How to Host a Mindustry Server in 2026: server-release.jar, Port 6567 and the Commands That MatterBlog7min
Recommended PC Tool
Recommended PC Tool
Crashes, No Sound, or Screen Glitches?Free driver scan
PC Slower Than It Used to Be?Free scan - under a minute

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.