- Durable execution का मूल इन्फ्रास्ट्रक्चर खुद नहीं, बल्कि workflow state को सुरक्षित रखना है; अगर प्रगति की स्थिति बची रहे, तो दोबारा चलाना और रिकवरी संभव है
- Obelisk workflow की प्रगति को execution log में सहेजता है और persist किए गए इतिहास से उसे replay करता है; इसकी संरचना activity retry के अनुरूप है
- SQLite अलग database service, network hop, या अतिरिक्त control plane के बिना local file के रूप में transaction-आधारित durable state देता है
- Litestream SQLite के बदलावों को S3-compatible object storage में asynchronously stream करता है, लेकिन कॉपी होने से पहले volume गायब हो जाए तो नवीनतम writes खो सकती हैं
- Obelisk Postgres को भी support करता है, और जब अधिक availability, shared scalability, या network database की विशेषताएँ चाहिए हों, तब वह अधिक उपयुक्त है
SQLite और Litestream का operating model
- Litestream SQLite के बदलावों को S3-compatible object storage में asynchronously stream कर सकता है
- काम की state को execution environment के करीब रखते हुए भी, backup, migration, और inspection के लिए database को बाहर कॉपी किया जा सकता है
- Asynchronous replication की प्रकृति के कारण, अगर SQLite volume कॉपी से पहले गायब हो जाए, तो restore के समय नवीनतम local writes खो सकती हैं
- संरचना यह है कि Obelisk server को SQLite database के साथ चलाया जाए, Litestream से backup लिया जाए, और जरूरत पड़ने पर observer आवश्यक database को लाए
- वही SQLite file local replay, debugging, और यह समझने के लिए इस्तेमाल की जा सकती है कि agent ने वास्तव में कौन-सा काम किया
उपयुक्त उपयोग-क्षेत्र और Postgres चुनने के मानदंड
- AI agents और AI-generated workflows अक्सर bursty और प्रयोगात्मक होते हैं, इसलिए agent या tenant के हिसाब से state की छोटी, self-contained units वाली संरचना समझने में आसान होती है
- micro VM या container के भीतर कई छोटे servers, जिनमें से हर एक के पास अपना SQLite database और object storage backup हो, एक बड़े हमेशा-चलते shared system की तुलना में अधिक सरल, सस्ता, और failure isolation के लिहाज से बेहतर हो सकता है
- अगर object storage के लिए asynchronous replication आपकी इच्छित durability model नहीं है, या अधिक availability, व्यापक shared scalability, या network database के गुण चाहिए, तो Postgres अधिक उपयुक्त है
- कई workflow systems को पहले दिन से उस स्तर के infrastructure की जरूरत नहीं होती, और state की जरूरत से बड़ा infrastructure लेकर शुरू करने की आवश्यकता नहीं है
- local SQLite database, S3 पर Litestream backup, और सस्ते workers के संयोजन से भी कम इन्फ्रास्ट्रक्चर वाला durable system बनाया जा सकता है, और AI agent क्षेत्र में यह एक उचित default हो सकता है
1 टिप्पणियां
Hacker News की राय
मैंने Temporal के साथ workflows बनाना शुरू किया है, जो एक local app के रूप में काफ़ी हल्के तरीके से deploy हो जाता है, और isolated local installs में SQLite का उपयोग करता है
API retries संभालना, workflows और tasks की cleanup करना सच में बहुत आसान हो जाता है, इसलिए इसे एक बार आज़माने की सलाह दूँगा। दार्शनिक रूप से यह ठीक उसी दिशा में है जैसा यह लेख सुझाता है, लेकिन इसमें agents के लिए इस्तेमाल करने लायक एक बहुत समृद्ध और लचीला interface भी जुड़ जाता है। Web UI में workflows देखना और agent executions की समीक्षा करना भी आसान है
Temporal सिस्टम में बहुत ज़्यादा reliability लगभग मुफ़्त में जोड़ देता है। Distributed और reliable systems कठिन होते हैं, इसलिए मेरा मानना है कि पहिया फिर से नहीं बनाना चाहिए
अगर आप SQLite database को आसानी से inspect करना चाहते हैं, workflow में क्या हो रहा है यह समझना चाहते हैं, individual tasks को compose करना चाहते हैं, और workflows को आसानी से callable बनाना चाहते हैं, तो Temporal देखने लायक है
इसके साथ ही agents के लिए files का उपयोग मैंने लगभग बंद कर दिया है। Markdown और JSON अच्छे हैं, लेकिन छोटे local apps बनाते समय वे किसी trap जैसे लगते हैं। LLMs SQLite को अच्छी तरह संभाल लेते हैं, और वहाँ से Markdown या JSON जैसे किसी भी format में render किया जा सकता है। अगर agent
jqचलाने या Markdown परgrepकरने के बजाय सिर्फ़ specific rows query कर सके, तो tokens की भी काफ़ी बचत होती है। इससे कई files की जगह एक ज़्यादा अनुशासित data structure बनाने के लिए मजबूर करने वाला, portable और self-contained data management system मिलता है। अगर कोई छोटा local project बड़ा हो जाए या ज़्यादा औपचारिक बन जाए, तो यह MySQL/Postgres तक भी आगे बढ़ सकता है, और तब तक आपके पास schema और data discipline पहले से मौजूद होता हैTemporal scale बढ़ने पर काफ़ी ज़्यादा जटिल हो जाता है। Cassandra चलाना मज़ेदार नहीं है, और Ringpop व TChannel में समस्या आने पर debug करना मुश्किल होता है। SQL backend support consistency requirements की वजह से horizontal scaling replicas को support नहीं करता और सिर्फ़ single instance पर संभव है
आप code कैसे लिखते हैं, इस पर निर्भर करते हुए workflows में embedded code को बदलना भी जटिल हो सकता है। History event order बदलने वाले changes पहले से deployed workers की determinism को तोड़ देते हैं
हम Temporal का बहुत उपयोग करते हैं; जो लोग simple scripting या automation से शुरू करते हैं, वे सब इसे पसंद करते हैं, और जो लोग उसके ऊपर वास्तविक production systems बनाते हैं, वे सब इसे नापसंद करते हैं। यह operational inexperience भी हो सकता है, लेकिन इन comments में जो बहुत चमकदार तस्वीर दिख रही है, वह मेरे अनुभव से मेल नहीं खाती
मैंने खुद नहीं किया है, लेकिन वास्तविक अनुभव और सुनना चाहूँगा
jqयाgrepके साथ Markdown इस्तेमाल करने के बजाय SQLite इस्तेमाल करने का कोई ठोस उदाहरण दे सकते हैं?प्रोडक्शन ऐप में SQLite इस्तेमाल करने की इस ज़िद को समझना मुश्किल है। SQLite एक embedded database है, इसलिए concurrency management के लिए बिल्कुल उपयुक्त नहीं है
इसी काम के लिए Postgres, MySQL जैसे database server मौजूद हैं। उनका पूरा मकसद यही है कि कई process अलग-अलग मशीनों से एक ही समय में data को modify कर सकें
यह computer science का बुनियादी सिद्धांत है, और जो लोग “हर चीज़ के लिए SQLite” कहते हैं, वे कुछ कम अनुभवी लगते हैं
SQLite कई वास्तविक workloads में एक बेहतरीन प्रोडक्शन database है, और यह बात व्यापक रूप से documented है। Postgres से यह इतना अलग है कि इसके लिए बिल्कुल अलग तकनीक सीखनी पड़ती है
एक नज़रिया यह है कि सिस्टम के जिन हिस्सों में स्वाभाविक रूप से मज़बूत partitioning होती है, वहाँ SQLite बहुत अच्छी तरह फिट हो सकता है
वास्तव में जो चीज़ छोड़ी जाती है, वह high availability/failover और disaster recovery है, लेकिन इनके भी समाधान मौजूद हैं। single-server system आम तौर पर हैरान करने वाली हद तक मज़बूत होते हैं, क्योंकि जब कोई जटिल control plane नहीं होता तो कई बार system बढ़ने के साथ uptime घट जाती है
मुझे तकनीकी बदलावों के संदर्भ में पुरानी “best practices” का फिर से मूल्यांकन करना पसंद है, खासकर जब उससे सादगी बढ़ती हो। परिवार के लिए social media site को एक VPS पर एक SQLite DB के साथ चलाना शानदार है। लगभग 15 user हैं और maintenance लगभग नहीं के बराबर है। FreshRSS instance और “now” page भी SQLite पर चलाता हूँ
काम पर भी पिछले कई दशकों में SQLite को हर तरह के कामों में इस्तेमाल किया है। temporary job queue, local पर बड़ी मात्रा में logs को तेज़ी से ingest/query करने, और simonw के शानदार https://github.com/simonw/datasette के साथ real-time display/filtering के लिए इस्तेमाल किया है
इसे “हर चीज़ के लिए SQLite” से ज़्यादा “सोच से कहीं ज़्यादा जगहों पर SQLite” कहना बेहतर होगा
kentonv/Cloudflare का edge SQLite काम शायद इस सोच को थोड़ा ज़्यादा लोकप्रिय बना गया हो, लेकिन यह रुझान पहले से मौजूद था। https://blog.cloudflare.com/sqlite-in-durable-objects/
ऐसे छोटे लेकिन उपयोगी use case को जानना और उनका इस्तेमाल करना अनुभव की कमी नहीं, बल्कि उल्टा अनुभव का संकेत हो सकता है
बहुत संभव है कि SQLite का इस्तेमाल बाकी सभी database engine को मिलाकर भी उनसे ज़्यादा होता हो। दुनिया में SQLite की अरबों copies मौजूद हैं। Android device, iPhone और iOS device, Mac, Windows 10/11 install, Firefox/Chrome/Safari, Skype, iTunes, Dropbox client, TurboTax और QuickBooks, PHP और Python, ज़्यादातर TV और set-top box, ज़्यादातर गाड़ियों के multimedia system, और अनगिनत applications में यह शामिल है
https://sqlite.org/mostdeployed.html
इससे scalability को समझना बहुत आसान हो जाता है। बस काटो, जोड़ो, फिर काटो, फिर जोड़ो। हर N user पर एक और shard जोड़ दो
बदले में cross-shard query, जैसे analytics, और user churn या aging होने पर load को कैसे balance किया जाए, जैसी दूसरी समस्याएँ आती हैं
लेकिन बड़े user scale पर insert/update से पैदा होने वाली shared index scaling की पूरी समस्या से बचा जा सकता है
तब यह relational database से ज़्यादा hierarchical database बन जाता है
इन सबको Go + SQLite से बदल दिया: Intercom, Zendesk, ईमेल मार्केटिंग, Kanban, Todo, payment stack, issue tracker, forum, uptime monitor, PagerDuty clone
बेचने के लिए मेरे पास दर्जनों products हैं, तो सोचा सब खुद ही क्यों न बना लूँ
ये सब एक ही server पर चलते हैं और बहुत कम memory इस्तेमाल करते हैं। पहले जिन SaaS tools का इस्तेमाल करता था, उन सबकी जगह इन्हीं ने ले ली
dedicated server पर migrate करने के बाद managed cloud solutions पर होने वाला खर्च लगभग 1/10 रह गया, और वही high availability बनाए रखते हुए latency भी कम हो गई। इसका एक कारण VPS के noisy neighbor की वजह से tail latency बढ़ना भी था
पहले इन चीज़ों पर बहुत पैसा खर्च होता था, लेकिन अब 4 महीने से production में चल रहा है और सिर्फ मामूली updates की ज़रूरत पड़ी है
deployment वाकई बहुत simple है। न Docker, न Kubernetes, सिर्फ systemd services और dev machine पर build करके deploy की गई binaries
MaxMind या IPData जैसी services पर भी पैसे देता था, लेकिन खुद की IP geolocation service बनाई और tests में यह ज़्यादातर मौजूदा solutions से बेहतर निकली
शुरुआत Uptime Robot के replacement के रूप में हुई, फिर confidence आया और PagerDuty को replace किया। उसके बाद Intercom को भी बदल दिया
आखिर में हमेशा सुनता था, “payment stack खुद मत बनाओ”, लेकिन YOLO सोचकर वह गलती खुद करके देखने का फैसला किया। मौजूदा payment solutions का अध्ययन करके खुद develop और deploy किया, और अब तक एक भी समस्या नहीं हुई
सामने Caddy रखा है
पता चला कि ज़्यादातर SaaS products जो features देते हैं, उनमें से वास्तव में मैं सिर्फ 1~5% ही इस्तेमाल कर रहा था, और जिन features की सच में ज़रूरत थी वे इन “enterprise-grade” platforms के भीतर लगातार और गहराई में दबते जाते थे, जिससे workflow और मुश्किल हो जाता था
commercial products नहीं दिखाऊँगा, क्योंकि partners और customers को शायद यह जानना पसंद न आए कि मैं कितना सस्ता हूँ, लेकिन मैं इसे resourcefulness कहता हूँ
free app दिखा सकता हूँ। हाल ही में launch की है और 20,000 से ज़्यादा users हैं: https://macrocodex.app/
यह app सिर्फ Zendesk clone इस्तेमाल करती है। ईमेल Cloudflare routing से handle होता है, इसलिए running cost लगभग न के बराबर है
file से multi-partition database तक बड़ा gap है। जब असली production दाँव पर हो, तब database को container में चलाना मेरी पसंद नहीं है
व्यक्तिगत रूप से, बहुत से ETL enterprise database लाए बिना local में ही process किए जा सकते हैं। ऐसे मामलों में DuckDB, SQLite से 5~10 गुना बेहतर है, और dedicated Postgres database खड़ा करने से कहीं ज़्यादा simple और fast है
सामान्य scripting में 20-line awk script और DuckDB-आधारित उससे कहीं ज़्यादा साफ़, robust और maintainable equivalent SQL script की तुलना ही नहीं की जा सकती
उम्मीद है MotherDuck को IPO के लिए pump-and-dump नहीं करना पड़ेगा। आम corporate greed की वजह से अगर यह tool खो गया तो दुख होगा
20-line awk script वाली बात मज़ेदार है। कल Ubuntu Summit में मैंने लगभग यही तर्क दिया था। एक point के बाद GNU coreutils के साथ shell scripts लिखना अव्यावहारिक हो जाता है, और DuckDB SQL scripts complexity, maintainability, और अक्सर performance में भी बेहतर scale करती हैं। slides यहाँ हैं: https://blobs.duckdb.org/slides/duckdb-ubuntu-summit-2026.pd... पेज 32~36
और MotherDuck, DuckDB के ऊपर proprietary-source DBaaS बनाता है। यह DuckDB के ऊपर बना है, और DuckDB से MotherDuck से connect किया जाता है, लेकिन यह Seattle स्थित एक अलग VC-funded company है
DuckDB को Amsterdam की bootstrap की हुई, यानी revenue-based company DuckLabs बनाती है। project की intellectual property तीसरे संगठन, Netherlands की non-profit DuckDB Foundation, के पास है। अधिक जानकारी के लिए https://duckdb.org/faq#how-are-duckdb-the-duckdb-foundation-... देखें
मैंने एक library बनाई है[0] जो S3 पर मौजूद SQLite DB को सुरक्षित तरीके से concurrent updates करने देती है
कम-ज्ञात SQLite sessions extension और छोटे metadata file पर S3 compare-and-swap का इस्तेमाल करके इसे काफ़ी efficient और safe बनाया है। कई छोटे projects में मज़े से इस्तेमाल कर रहा हूँ जहाँ Lambda functions के लिए stateful DB चाहिए, लेकिन पूरे database instance का खर्च नहीं उठाना चाहते
[0]: https://github.com/psanford/s3db
single-node application में SQLite, Postgres की तुलना में भी हैरान कर देने वाली performance देता है
Postgres बहुत ज़्यादा memory खाता है, और I/O को inter-process communication से होकर गुजरना पड़ता है। दूसरी ओर SQLite में shared connection pool के जरिए सब कुछ process के अंदर रखा जा सकता है
agent harness के लिए कई storage engines test कर रहा हूँ; SQLite के साथ single vCPU पर 7.5k concurrent sessions तक जा सका, लेकिन Postgres crash हो गया या connections खत्म हो गए
[0] https://github.com/impalasys/talon/pull/23#issuecomment-4577...
जैसे ही आप current thread से बाहर जाते हैं, latency के हिसाब से खेल हारने लगते हैं। अगर inter-thread communication को मजबूर न किया जाए, तो SQLite microsecond-level timings पर काम कर सकता है
single-node context में Postgres overkill है। उससे SQLite से प्रतिस्पर्धा की उम्मीद नहीं करनी चाहिए
यह कुछ वैसा ही है जैसे in-memory HashMap और Redis को benchmark करके ideal conditions में HashMap के अच्छा निकलने पर हैरान होना
कई सालों तक SQLite के बारे में पढ़ने के बाद इसे एक side project में इस्तेमाल किया, और Postgres से आने पर इसका type system इतना कमजोर लगा कि झटका लगा
सच में बहुत घटिया है, समझ नहीं आता कि इसकी इतनी तारीफ़ क्यों होती है
https://sqlite.org/datatype3.html
https://www.postgresql.org/docs/current/datatype.html
date/time को हैंडल करना ऐसा लगता है जैसे 30 साल पुराना database इस्तेमाल कर रहे हों, और insert करते समय कुछ भी enforce नहीं होता। इतने लोग इसे क्यों पसंद करते हैं, कोई समझाए
PRAGMA journal_mode = WAL
PRAGMA foreign_keys = ON
Something non-null
PRAGMA busy_timeout = 1000This is fine for most applications, but see the manual
PRAGMA synchronous = NORMALIf you use it as a file format
PRAGMA trusted_schema = OFFbinding के हिसाब से extra options की ज़रूरत पड़ सकती है। उदाहरण के लिए, Python applications को sqlite3 module के default settings इस्तेमाल नहीं करने चाहिए। वह default बस गलत है। 3.12 से पहले standard library के बाहर की bindings इस्तेमाल करने के अलावा कोई विकल्प भी नहीं था: https://docs.python.org/3/library/sqlite3.html#transaction-c...
strict tables भी इस्तेमाल करने चाहिए। https://www.sqlite.org/stricttables.html
usability खराब है, लेकिन CHECK constraints भी इस्तेमाल किए जा सकते हैं। उदाहरण के लिए, SQLite की built-in date support से यह किया जा सकता है, हालांकि थोड़ा अटपटा है:
CHECK (
date(my_date_col) IS NOT NULL
AND my_date_col = date(my_date_col)
)
IS NOT NULL की ज़रूरत इसलिए है क्योंकि गलत date होने पर date NULL लौटाता है। दूसरी check की वजह यह है कि वह Julian day भी स्वीकार कर लेती है, इसलिए date('2026') ईसा पूर्व 4707 के किसी समय पर पहुँच जाता है
खासकर strict tables से पहले यह निराशाजनक था, इस बात से सहमत हूँ
DuckDB देखना चाहिए। यह सही types वाले SQLite के ज़्यादा करीब है। हालांकि यह OLTP, यानी array of structs, नहीं बल्कि OLAP, यानी struct of arrays, है, इसलिए सामान्य SQLite workloads में performance खराब हो सकती है। असल में अगर कोई application इन दोनों में से किसी एक पर विचार कर रही है, तो शायद फ़र्क बहुत बड़ा नहीं होगा
कई बड़े Postgres clusters चलाने के बाद मैं SQLite पर आ गया, और 7-अंकीय monthly active users वाली service पूरी तरह SQLite durable objects पर टिकी है
access patterns के बारे में अलग तरह से सोचना पड़ता है, लेकिन फायदे उसके लायक थे
framing अच्छा है। अगर मुख्य समस्या workflow state को durably store करना है, ताकि उसे inspect किया जा सके और आसानी से recover किया जा सके, तो SQLite कई बार पर्याप्त होता है
इस idea की अगली iteration के रूप में “durable workflows के लिए सिर्फ logs काफ़ी हैं” देखने का इंतज़ार है
“सिर्फ logs काफ़ी हैं” तरह के solutions के fail होने की एक वजह यह हो सकती है कि untrusted logs injection attack बन जाएँ[1]
SBOM चेक करना चाहिए, और CI/CD pipeline को शामिल करना भूलना नहीं चाहिए[2]
[1] https://news.ycombinator.com/item?id=48315440
[2] https://github.com/jqwik-team/jqwik/issues/708#issuecomment-...
गंभीरता से कहें तो, expert वही है जो काम के हिसाब से सही tool इस्तेमाल करे