- Durable workflow execution state को डेटाबेस में checkpoint करता है, ताकि crash के बाद आखिरी पूरी हुई step से recovery हो सके
- Temporal, Airflow, AWS Step Functions जैसे external orchestration मॉडल एक central orchestrator और storage जोड़ते हैं, जिससे complexity बढ़ती है
- Postgres-आधारित architecture में application server workflow table को poll करते हैं और step output को सीधे store करते हैं, जिससे recovery संभव होती है
- कई server locks और integrity constraints से duplicate execution रोकते हैं, और scalability, availability, observability की समस्याओं को Postgres के solutions से संभालते हैं
- एक single Postgres प्रति सेकंड दसियों हज़ार workflow तक vertical scale कर सकता है, और replication, multi-AZ, SQL analytics का सीधा लाभ लिया जा सकता है
Durable workflow का मूल मॉडल
- Durable workflow वह तरीका है जिसमें program execution के दौरान progress state को समय-समय पर checkpoint के रूप में डेटाबेस में save किया जाता है, ताकि crash या failure के बाद आखिरी पूरी हुई step से recovery की जा सके
- इसे video game के save और load की तरह समझा जा सकता है, जहाँ program progress को नियमित रूप से “save” किया जाता है और crash के बाद आखिरी checkpoint से “load” किया जाता है
- इसका सामान्य implementation Temporal, Airflow, AWS Step Functions जैसे external orchestration systems हैं
- External orchestration में durable program को कई steps वाले workflow के रूप में लिखा जाता है, और एक central orchestrator execution को coordinate करता है
External orchestration कैसे काम करता है
- जब client workflow submit करता है, तो orchestrator data store में record बनाता है और execution के लिए उसे worker को dispatch करता है
- हर step पूरी होने पर worker result orchestrator को भेजता है, और orchestrator उस output को data store में checkpoint करने के बाद अगली step dispatch करता है
- अगर worker crash हो जाए या fail हो जाए, तो orchestrator उस workflow को किसी दूसरे worker को फिर से dispatch करता है और उसे आखिरी checkpointed step से शुरू कराता है
- यह architecture workflow state को डेटाबेस में store करने के मूल विचार पर अलग orchestrator server जोड़कर complexity बढ़ा देता है
Postgres को orchestrator की तरह इस्तेमाल करने वाला architecture
- अगर durable workflow का मूल विचार program state को डेटाबेस में checkpoint करना है, तो अलग orchestrator server के बिना डेटाबेस खुद को orchestrator की तरह इस्तेमाल करना अधिक सरल और efficient है
- Postgres अपनी लोकप्रियता, scalability, और समृद्ध ecosystem के कारण durable workflow बनाने के लिए उपयुक्त विकल्प है
- Postgres-आधारित durable workflow system में application server किसी central orchestrator से गुज़रे बिना सीधे Postgres से communicate करके workflow चलाते हैं
- Client execution submit करने के लिए Postgres की workflow table में entry बनाता है, और application server उस table को poll करके workflow dequeue और execute करते हैं
- Workflow execute करते समय server हर step का output Postgres में checkpoint करते हैं, और अगर running server crash हो जाए या fail हो जाए, तो दूसरा server checkpoint से workflow recover कर लेता है
Central orchestrator की ज़रूरत क्यों नहीं रहती
- Application servers Postgres के ज़रिए coordinate कर सकते हैं, इसलिए किसी central orchestrator को workflow workers तक dispatch करने की ज़रूरत नहीं होती
- Servers Postgres tables से मिलकर workflow dequeue कर सकते हैं, और locking clauses जैसे mechanisms से यह सुनिश्चित कर सकते हैं कि हर workflow ठीक एक ही worker द्वारा dequeue हो
- Step output checkpoints भी orchestrator नहीं, बल्कि worker सीधे Postgres में लिखते हैं
- अगर कई workers एक ही workflow को एक साथ execute करने की कोशिश करें, तो Postgres की integrity constraints checkpoint के समय duplicate work को detect करके पीछे हटने पर मजबूर कर सकती हैं
- Central orchestrator को Postgres या किसी अन्य डेटाबेस से replace करने पर scalability, availability, observability, security जैसी समस्याओं को well-known Postgres-native solutions से संभाला जा सकता है
Scalability और availability
- Database-आधारित durable workflow systems की scalability और availability मूल रूप से underlying database से तय होती है
- अधिक worker servers जोड़कर horizontal scale किया जा सकता है, इसलिए अधिकतम throughput इस बात पर निर्भर करता है कि database workflow को कितनी तेज़ी से process कर सकता है
- Workers एक-दूसरे के स्थान पर काम कर सकते हैं और एक-दूसरे की state recover कर सकते हैं, इसलिए जब तक underlying database उपलब्ध है, system available रहता है
- Postgres इस्तेमाल करने का लाभ यह है कि scalability और availability लंबे समय से शोधित समस्याएँ हैं और इनके लिए मजबूत solutions मौजूद हैं
- एक single Postgres server प्रति सेकंड दसियों हज़ार workflow process करने के लिए vertical scale किया जा सकता है
- अतिरिक्त scale CockroachDB जैसे distributed Postgres या sharded Postgres से हासिल किया जा सकता है
- Postgres automatic failover के साथ streaming replication को support करता है, और managed services आमतौर पर multi-AZ deployment और high-availability SLA देती हैं
- बड़े पैमाने पर Postgres चलाने के लिए दशकों में संचित engineering और research durable workflow operations में भी सीधे काम आ सकती है
Observability
- Postgres-आधारित durable execution में workflows और steps Postgres tables में checkpoint किए जाते हैं, इसलिए उन checkpoints को scan करके workflows को real time में monitor और executions को visualize किया जा सकता है
- यह Postgres की ताकत है कि लगभग हर workflow observability query को SQL में व्यक्त किया जा सकता है
- पिछले एक महीने में error वाले सभी workflows ढूँढने जैसी complex filtering और analysis को SQL में declaratively व्यक्त किया जा सकता है
- यह Postgres के relational model और query optimization पर दशकों के research का लाभ उठाने से संभव होता है
- लोकप्रिय external orchestrators द्वारा इस्तेमाल किए जाने वाले key-value store जैसे सरल data model वाले कई systems इसी स्तर का SQL-आधारित analysis support नहीं दे पाते
- Workflow और step data को Postgres tables में store करके और तेज़ analytical queries के लिए secondary indexes जोड़कर durable execution में efficient observability हासिल की जा सकती है
Reliability और security
- External orchestrator का उपयोग करने वाले durable execution में orchestrator और उसका data store दोनों single point of failure बन जाते हैं
- क्योंकि orchestrator और data store सीधे workflow execution को coordinate करते हैं, इसलिए इनमें से कोई एक भी down हो जाए तो पूरी application unusable हो सकती है
- ये workflow और step checkpoints को handle और store करते हैं, इसलिए इनके पास sensitive application data तक पहुँच हो सकती है; इस कारण इन्हें sensitive infrastructure की तरह hardening, access control, और auditing की ज़रूरत होती है
- Postgres-आधारित durable execution में एकमात्र failure point Postgres ही होता है, और सारा workflow data सीधे Postgres में store होता है, किसी दूसरे system से होकर नहीं गुजरता
- अगर application पहले से ही Postgres पर निर्भर है, तो durable execution अपनाने से कोई नया failure point नहीं जुड़ता और न ही कोई नया attack surface बनता है जिसे secure करना पड़े
- Database पहले से ही core infrastructure है, इसलिए orchestration के लिए नया core infrastructure जोड़ने के बजाय मौजूदा database का reuse करना अधिक उचित है
और जानें
1 टिप्पणियां
Hacker News टिप्पणियाँ
Armin Ronacher का
absurd, Postgres के लिए durable workflow का implementation हैhttps://lucumr.pocoo.org/2025/11/3/absurd-workflows/
https://github.com/earendil-works/absurd
https://earendil-works.github.io/absurd/
मैंने इसे खुद इस्तेमाल नहीं किया है, लेकिन दूसरे विकल्पों के साथ तुलना करने लायक लगता है
absurdऔर उसका Rust-derived implementationdurable, client side को बेहद simple रखने के लिए अच्छे विकल्प लगते हैंये हल्के हैं, इसलिए coding agent पूरे structure को आसानी से दिमाग में रख सकता है, और ज़रूरत पड़े तो query से state देखी जा सकती है
मैं dbos.dev, restate.dev, cf workflows इस्तेमाल कर रहा हूँ, और हमारे Agents.md में यह लिखा है
Restate.dev का उपयोग northflank के payment integration के लिए करते हैं। यह cf workflows से तेज़ है, Cloudflare और उसके outages से स्वतंत्र है, और self-host किया जा सकता है, इसलिए vendor lock-in नहीं है
Cloudflare workflows का उपयोग CSV/PDF report generation जैसे कम-महत्व वाले कामों के लिए करते हैं। क्योंकि यह बहुत सस्ता है
DBOS.dev का उपयोग उन workflows के लिए करते हैं जिन्हें Postgres transactions से बंधी atomic messaging चाहिए और 100% reliability/durability ज़रूरी होती है। जैसे materialized row भरना या merchants को महत्वपूर्ण email/push भेजना
DBOS और Restate ऊपर-ऊपर से समान दिखते हैं, लेकिन Restate को एक केंद्रीय “orchestrator” चाहिए, जिसके अपने फायदे-नुकसान हैं, और इससे cf/vercel के serverless workers के साथ बनाना आसान हो जाता है
साथ ही इसमें VirtualObject है, इसलिए यह Cloudflare के single-threaded DurableObject का vendor lock-in रहित open source विकल्प भी ठीक लगता है
DBOS खास तौर पर दो जगह चमकता है। 1)
dbos.enqueue_workflowके ज़रिए business logic वाले उसी DB transaction के अंदर atomic messaging की जा सकती है। यह हिस्सा अक्सर किसी भी समाधान में सबसे fragile होता है, इसलिए business logic चलाने वाले उसी transaction में इसे atomic और durable तरीके से संभालने से complexity काफ़ी घट जाती है2) DBOS workflow state को DB में स्टोर करता है, इसलिए metabase/looker से observability dashboard बनाना आसान होना चाहिए। अच्छा होगा अगर Restate भी rocksdb instance को expose करे ताकि उसे metabase से जोड़ा जा सके
DBOS और Temporal इस्तेमाल कर चुके लोगों का व्यावहारिक अनुभव जानने की जिज्ञासा है
मैंने पहले Temporal इस्तेमाल किया है और यह काफ़ी अच्छी तरह काम करता था, लेकिन request payload या event size limits की वजह से समाधान बनाते समय कभी-कभी असुविधा हुई
अच्छी engineering practices को enforce करने का फ़ायदा है, लेकिन सिर्फ़ इसलिए कि CSV फ़ाइल 2MB से बड़ी है, उसे S3 पर अपलोड करके लिंक पास करना और फिर workflow में दोबारा डाउनलोड करने वाली विशेष logic हर बार इस्तेमाल करना मैं नहीं चाहूँगा
DBOS का अनुभव कैसा है, और operational complexity या feature parity जैसी बातों में यह Temporal से कैसे तुलना करता है, यह जानना चाहता हूँ
घर पर भी इसे time-sensitive न होने वाले home automation tasks संभालने के लिए चला रहा हूँ। Workflow latency बहुत बुरी नहीं है, लेकिन घर के motion detection events जैसे triggers के लिए, जहाँ तुरंत प्रतिक्रिया चाहिए, मैं इसका उपयोग नहीं करूँगा; हालाँकि inactivity के बाद कुछ बंद करने वाले timeout जैसे कामों के लिए यह ठीक है
VPC या Kubernetes cluster के अंदर Temporal के सामने एक पतली REST API रखने का तरीका मुझे काफ़ी पसंद है। इससे event-based triggers को Temporal authentication या workflow status checks की चिंता नहीं करनी पड़ती, और events को यथासंभव logic-free रखने में मदद मिलती है
उदाहरण के लिए, कोई DB trigger सीधे चलता है या event को queue में डालता है, और handler ज़रूरी event details के साथ उस पतली REST API को call करता है। REST API तय कर सकती है कि workflow शुरू करना है, किसी मौजूदा workflow को signal भेजना है, या इसे ignore करना है। Pattern हर स्थिति में अलग हो सकता है, लेकिन मेरे मामले में मैं अक्सर
SignalWithStartइस्तेमाल करता हूँ, या अगर शुरू करना उचित नहीं है और कोई मौजूदा workflow भी नहीं है, तो उसे बस छोड़ देता हूँसाथ ही, जब किसी एक object lifecycle में एक-दूसरे से स्वतंत्र actions को orchestrate करना हो, तो parent/child workflow फीचर बहुत उपयोगी होता है, और यह भी अच्छा है कि बाहरी कारक object की प्रगति का रास्ता बदल दें तो cancellation संभव है
लंबी और थोड़ी अस्पष्ट बात करूँ तो, यह बहुत शक्तिशाली है, संभालने में आसान है, और lifecycle logic को API के बाहर निकालने में बहुत मदद करता है। अगर इसे API के अंदर रखो तो technical debt जल्दी जमा होता है और maintainability अस्थिर हो जाती है। जो logic आसानी से दिखने वाली जगह पर डाल दी जाती है और बाद में छिपा हुआ जाल बन जाती है, उससे बेहतर है कि यह best practices का पालन करवाए—इस बात से मैं सहमत हूँ
लेकिन Cloud product आज़माया और कीमत देखकर हैरान रह गया। Production में जाने से पहले ही 1,000 डॉलर के free credits ख़त्म कर दिए। Local Temporal खुद operate करने की भी इच्छा नहीं थी
व्यक्तिगत रूप से मुझे सबसे अच्छा यह लगता है कि architecture से सिर्फ़ ideas लेकर Postgres पर खुद implementation की जाए
यह मुझे 100% पसंद नहीं है। यह किसी मूलभूत हिस्से से ज़्यादा बाद में जोड़ी गई चीज़ जैसा लगता है, और अभी शुरुआती release है। फिर भी, फ़िलहाल इसे व्यावहारिक रूप से solved माना जा सकता है
Production में एक साल से ज़्यादा चलाने के अनुभव से कहूँ तो Temporal का design अच्छा नहीं है, यह धीमा है, और infrastructure के हिसाब से बेहद भारी है
अगर काम मामूली न हो—जैसे प्रति workflow 200 से ज़्यादा events हों और एक समय में कुछ सौ workflows पूरे दिन चलते रहें—तो सिर्फ़ infrastructure cost पर ही कई मिलियन डॉलर लग सकते हैं, और तब भी अनुभव अच्छा नहीं रहता
अपने benchmarks चलाने पर numbers बहुत खराब आते हैं
Sales team भी सचमुच बहुत खराब है और काफ़ी हताश लगती है
Developer नज़रिए से SDK काफ़ी अच्छा है
nexus में फँसने से बचें, और sales team फ़ोन करे तो कमरे में legal team को ज़रूर साथ रखें
Celery से कैसे migrate करें, यह समझने में समय लगा, लेकिन हमारे use case में यह उसके लायक था
Conductor OSS भी यह काफ़ी अच्छी तरह करता है https://docs.conductor-oss.org/devguide/ai/index.html
https://github.com/agentspan-ai/agentspan मूल रूप से Conductor के लिए एक agent SDK layer है, जो langgraph, OpenAI, vercel, और ADK agents को बिना code changes के durable बना सकती है और orchestration जोड़ सकती है
Data store, state machine, valid state constraints, और valid states के बीच transition करने वाली logic को अलग-अलग रखने के बजाय, काश इन्हें app state के किसी kernel में एकीकृत किया जा सकता
सच कहूँ तो Postgres में पहले से ही ऐसी बहुत क्षमता है, लेकिन app या product level पर ऐसा कोई स्पष्ट चित्र अभी नहीं दिखता जो app के transition कर सकने वाले प्रमाणित states का set दे, और उसे clients के लिए उपयोगी तरीके से अपने-आप expose करे। उदाहरण के लिए, यह user इस post को like कर सकता है लेकिन edit नहीं कर सकता
मेरी नज़र में यह colored Petri net जैसा दिखता है, लेकिन जैसे database की स्पष्ट सफलता-सीमाएँ होती हैं, वैसे सरल app-state paradigm की तस्वीर अभी नज़र नहीं आती
हालाँकि यह पूरी तरह integrated है या नहीं, इस पर मुझे भरोसा नहीं है
DBOS Rust को support नहीं करता, इसलिए मैंने https://github.com/tensorzero/durable में इसका एक बहुत minimal Rust version implement किया
यह काफ़ी stable और scalable निकला, लेकिन स्वाभाविक रूप से SQL implementation के मामले में बहुत सावधानी रखनी पड़ती है। उम्मीद है यहाँ के पाठकों को यह दिलचस्प लगेगा
https://flawless.dev/
कॉन्सेप्ट पूरी तरह समझ में आता है और मैं इससे सहमत हूँ। इस तरह की durability को workflow system में डालने का यह शानदार तरीका है
बस gamer दिमाग से मैं इसे “बड़े पैमाने पर save scumming” कहना चाहूँगा। बहुत से लोग पहले से जानते होंगे कि यह approach काम करती है, लेकिन हो सकता है वे इसे abstract computer science concepts से जोड़ न पाए हों
robustness बढ़ाने की एक और strategy यह है कि workflow को idempotent operations से बनाया जाए। यह उन हालात में उपयोगी हो सकता है जहाँ workflow state इतनी बड़ी हो कि उसका backup लेना मुश्किल हो। इसकी जगह अगर काम को शुरुआत से फिर चलाया जाए, तो जहाँ तक पहले से प्रगति हो चुकी है वहाँ तक सब no-op बन जाएगा
यह बात लगातार हैरान करती है कि अगर Postgres toolkit में हो, तो बहुत कम tools के साथ कितना कुछ किया जा सकता है
मैंने हाल ही में एक distributed queue बनाई, और वह सचमुच बहुत अच्छी तरह काम करती है, benchmark भी अच्छे हैं, और race conditions या conflicts भी नहीं हैं। workers को सुरक्षित रूप से compete करने देने के लिए मैंने
SKIP LOCKEDका इस्तेमाल कियाकई nodes पर फैले workers को टकराव से बचाने के लिए session-scoped mutex, यानी
pg advisory lock, भी इस्तेमाल किया जा सकता हैSELECT FOR UPDATEहोल्ड करने पर scaling अच्छी नहीं रहतीसंपादन: दोबारा जाँचने पर लगता है कि अब सलाह उलट गई है
Rails में database-backed job backends कई हैं, लेकिन convention के अनुसार job को हमेशा सिर्फ एक ही काम करना चाहिए और जहाँ तक संभव हो बहुत जल्दी खत्म हो जाना चाहिए
इस वजह से workflow बनाना थोड़ा बनावटी लगने लगता है। पहले job की आखिरी line में दूसरे job को queue करना, फिर दूसरे job की आखिरी line में तीसरे job को queue करना—कुछ ऐसा हो जाता है
job backend इन्हें जुड़े हुए workflow की तरह नहीं दिखाता, बल्कि independent jobs की तरह संभालता है, और अगर workflow को high level पर समझना हो तो कई job classes पढ़नी पड़ती हैं
Rails ने हाल ही में jobs के अंदर step-by-step checkpoint लेकर resume करने के लिए continuable का concept जोड़ा है, लेकिन फिर भी job को single responsibility तक सीमित रखने की convention इतनी मजबूत है कि इसे असली workflow के लिए इस्तेमाल करना थोड़ा अटपटा लगता है
जानना चाहूँगा कि क्या और लोगों ने भी ऐसा झेला है, और क्या उन्हें इसका कोई समाधान मिला
यह शानदार pattern है। जितना संभव हो, उतना काम database के अंदर करना बेहतर है
बाहरी Spanner change streams देता है। आंतरिक Spanner अलग है; इसकी मुख्य वजह यह है कि कुछ मामलों में बहुत extreme scaling requirements होती हैं, और इसके साथ “जो पहले से अच्छा चल रहा है” वाली वजह और “arbitrary change stream डरावनी है” वाली वजह भी जुड़ी हुई है
आंतरिक Spanner किसी भी transaction को queue entry लिखने देता है। यहाँ queue मोटे तौर पर एक ऐसी table है जिसमें समय की विशेष समझ होती है। delivery को schedule किया जा सकता है, entries को queue से handler तक push किया जाता है, और handler dequeue transaction के भीतर ही DB writes भी कर सकता है। और वही सारी scalability भी बनी रहती है