Have you seen the ingestion pipeline? If you attach a docstore and vectorstore to it, it will handle upserts for you
pipeline = IngestionPipeline(..., docstore=docstore, vector_store=vecstor_store)
pipeline.run(documents=documents)
index = VectorStoreIndex.from_vector_store(vector_store)
Just have to make sure the docstore is saved somewhere (to disk, or using integrations like mongodb, redis, etc.)