Event sourcing என்பது உங்கள் தரவை மீண்டும் மீண்டும் மாற்றியமைப்பதைத் (overwriting) தவிர்க்கச் சொல்கிறது. ஒரு பாரம்பரிய CRUD பயன்பாட்டில், பயனரின் ஷிப்பிங் முகவரியைப் புதுப்பிப்பது என்பது அந்த வரிசையைக் (row) கண்டுபிடித்து, மதிப்பை மாற்றிவிட்டு, முந்தைய நிலையைத் தூக்கி எறிவதாகும். Event sourcing ஒரு மாறுபட்ட பாதையைத் தேர்ந்தெடுக்கிறது. இது ஒவ்வொரு மாற்றத்தையும் மாற்ற முடியாத ஒரு உண்மையாக (immutable fact) சேமிக்கிறது: ஒரு பயனர் கணக்கைத் தொடங்கினார், முகவரியைப் புதுப்பித்தார், மின்னஞ்சலைச் சரிபார்த்தார். அமைப்பின் தற்போதைய நிலை நேரடியாகச் சேமிக்கப்படுவதில்லை. இந்த நிகழ்வுகளை வரிசைப்படி மீண்டும் இயக்குவதன் (replaying) மூலம் அது கணக்கிடப்படுகிறது.

இந்த முறை நிஜமான சிக்கல்களைத் தீர்க்கிறது. தணிக்கைப் பதிவுகள் (Audit trails) தானாகவே கிடைக்கும் கூடுதல் பயன்களாகிவிடும். ஒரு ஆர்டரின் நிலையை கடந்த காலத்தின் எந்தவொரு தருணத்திலும் நீங்கள் மீண்டும் உருவாக்க முடியும். என்ன நடந்தது என்பதைத் துல்லியமாக மீண்டும் இயக்கி (replaying) பிழைகளைத் திருத்த முடியும் (debug). இதன் சவாலான விஷயம் சிக்கல்தன்மை (complexity) ஆகும். இப்போது நீங்கள் எளிய வரிசைகளுக்குப் பதிலாக, உண்மைகளின் ஓட்டங்கள் (streams of facts), ரீட் மாடல்கள் (read models) மற்றும் காலப்போக்கில் ஏற்படும் ஒருமைப்பாடு (eventual consistency) ஆகியவற்றை நிர்வகிக்க வேண்டியிருக்கும்.

PostgreSQL உங்கள் event store ஆகச் செயல்பட முடியும். பெரும்பாலான குழுக்கள் ஏற்கனவே இதைப் பயன்படுத்துகின்றன. இது ACID பரிவர்த்தனைகள், நெகிழ்வான தரவுகளுக்கான JSONB மற்றும் நிரூபிக்கப்பட்ட பேக்கப் கருவிகளை வழங்குகிறது. முதல் நாளிலேயே Kafka, Cassandra அல்லது ஒரு பிரத்யேக event-store தரவுத்தளத்தை நீங்கள் அறிமுகப்படுத்த வேண்டிய அவசியமில்லை. ஒரு நிலையான Postgres instance, உங்கள் உள்கட்டமைப்பை (infrastructure) விரிவாக்காமலேயே, event sourcing கோரும் பரிவர்த்தனை உத்தரவாதங்களையும் (transactional guarantees) தணிக்கைப் பதிவுகளையும் உங்களுக்கு வழங்குகிறது.

ஒரு Postgres Event Store-ன் வடிவம்

இதன் ஸ்கீமா (schema) வியக்கத்தக்க வகையில் எளிமையாக இருக்கலாம். குறைந்தபட்சம், நிகழ்வுகளைச் சேர்க்கும் (append) மற்றும் அவற்றை ஒரு இடத்திலேயே மாற்றாத (never updates in place) ஒரு அட்டவணை உங்களுக்குத் தேவைப்படும். ஒரு நடைமுறை வடிவமைப்பு இவ்வாறு இருக்கும்:

  • உலகளாவிய வரிசைப்படுத்தலுக்கு (global ordering) உதவும் வகையில் id என்பது bigserial அல்லது UUID ஆக இருக்கலாம்.
  • தொடர்புடைய நிகழ்வுகளைக் குழுவாக்க stream_id பயன்படும் (உதாரணமாக, ஒரு பயனர் அல்லது ஆர்டருக்கான அனைத்து மாற்றங்கள்).
  • event_type என்பது சாதாரண உரையாக (plain text) இருக்கும்: UserEmailChanged, PaymentReceived, InventoryAdjusted.
  • அந்த நிகழ்விற்கான குறிப்பிட்ட தரவைச் சேமிக்க payload என்பது JSONB ஆக இருக்கும்.
  • நேர மண்டலத் துல்லியத்துடன் (timezone precision) occurred_at.
  • ஒவ்வொரு stream-க்கும் ஒரு version, இது நம்பிக்கையான இணக்கத்தன்மையை (optimistic concurrency) உறுதி செய்யும்.

நீங்கள் பயன்பாட்டு குறியீட்டில் (application code) அல்லது தரவுத்தளக் கட்டுப்பாட்டின் (database constraint) மூலம் இந்த மாற்ற முடியாத விதியைப் (immutability rule) பின்பற்றலாம். (stream_id, version) ஆகியவற்றின் மீது ஒரு தனித்துவமான குறியீட்டை (unique index) உருவாக்குவதன் மூலம், இரண்டு பயனர்கள் ஒரே வரிசை எண்ணைச் சேர்க்காமல் தடுக்கலாம். ஒரு கட்டளை (command) வரும்போது, அந்த stream-க்கான தற்போதைய பதிப்பை (version) நீங்கள் படித்து, அதை அதிகரித்து, ஒரு பரிவர்த்தனைக்குள் (transaction) புதிய நிகழ்வைச் சேர்க்க வேண்டும். மற்றொரு செயல்முறை உங்களை விட முன்னதாகச் செய்துவிட்டால், தனித்துவமான கட்டுப்பாடு (unique constraint) தோல்வியடையும், அப்போது நீங்கள் மீண்டும் முயற்சிக்கலாம் அல்லது கட்டளையை நிராகரிக்கலாம்.

ஒரு நடைமுறை உதாரணத்தைக் கருத்தில் கொள்ளுங்கள். நீங்கள் ஒரு சரக்கு மேலாண்மை அமைப்பை (inventory system) இயக்குகிறீர்கள். quantity நெடுவரிசையுடன் கூடிய ஒரு ஒற்றை inventory வரிசைக்கு பதிலாக, நீங்கள் inventory_events என்ற அட்டவணையில் நிகழ்வுகளைச் சேர்க்கிறீர்கள். ItemReceived என்பது பத்து அலகுகளைச் சேர்க்கிறது. ItemReserved என்பது இரண்டை நீக்குகிறது. ItemShipped என்பது மூன்றை நீக்குகிறது. SKU-42-க்கான தற்போதைய இருப்பைத் தெரிந்துகொள்ள, தொடர்புடைய நிகழ்வுத் தரவுகளை (event payloads) நீங்கள் கூட்ட வேண்டும். மூன்று நாட்களுக்கு முன்பு இருந்த இருப்பைத் தெரிந்துகொள்ள, அந்தத் timestamp வரை உள்ள நிகழ்வுகளை மட்டும் கூட்ட வேண்டும். கடந்த செவ்வாய்க்கிழமை உங்கள் ஷிப்பிங் லாஜிக்கில் ஒரு பிழை ஏற்பட்டிருந்தால், சரியான குறியீட்டின் மூலம் நிகழ்வுகளை மீண்டும் இயக்கி உண்மையான நிலையைப் பெறலாம். ஒரு சாதாரண UPDATE அறிக்கையைக் கொண்டு இதைச் செய்ய முடியாது.

சிக்கல்களைத் தவிர்க்க உதவும் கொள்கைகள்

Postgres-ஐ அடிப்படையாகக் கொண்டு உருவாக்குவது ஒழுக்கத்தின் (discipline) தேவையை நீக்கிவிடாது. பின்வரும் கொள்கைகள் event-sourced அமைப்புகளுக்கு நேரடியாகப் பொருந்தும்.

எளிமையாக வைத்திருங்கள். சிக்கல்தன்மை நம்பகத்தன்மையைக் கொல்லும். ஒரு செயல்பாட்டை வெற்றிகரமாகச் செயல்படுத்தும் முன்பே, ஒரு பொதுவான event framework-ஐ உருவாக்கத் தூண்டப்பட வேண்டாம். ஒரு தனி அட்டவணை, நிகழ்வுகளைச் சேர்க்க ஒரு repository function மற்றும் ரீட் மாடல்களை உருவாக்க ஒரு projection worker ஆகியவை அதன் மதிப்பை நிரூபிக்க போதுமானவை. ஒரு குறிப்பிட்ட சிக்கல் எழும்போது மட்டும் கூடுதல் கருவிகளைச் சேர்க்கவும்.

சிறிய அளவில் தொடங்குங்கள். உங்கள் முழுமையான மோனோலித் (monolith) அமைப்பையும் மாற்றி எழுத வேண்டாம். தணிக்கைப் பதிவுகள் (audit trail) கூடுதல் சுமையைத் தாங்கும் அளவுக்குத் தேவையான ஒரு குறிப்பிட்ட பகுதியை மட்டும் தேர்ந்தெடுங்கள். ஒரு பில்லிங் லெட்ஜர் (billing ledger), ஒரு பணிப்பாய்வு இயந்திரம் (workflow engine) அல்லது ஒரு சரக்கு முன்பதிவு அமைப்பு ஆகியவை சிறந்த தேர்வாக இருக்கும். அந்த ஒரு குழாயை (pipeline) முழுமையாக உருவாக்கி, அதைத் தயாரிப்புச் சூழலில் (production) இயக்க விடுங்கள். அதன் பிறகு விரிவாக்கலாமா வேண்டாமா என்று முடிவு செய்யுங்கள்.

வெற்றியை முதலில் வரையறுக்கவும். Event sourcing என்பது இயல்பாகத் தேர்ந்தெடுக்கப்பட வேண்டிய கட்டமைப்பு அல்ல; அது குறிப்பிட்ட தேவைகளுக்கான ஒரு தீர்வாகும். உங்கள் தேவை சமீபத்திய நிலையை மட்டும் கண்காணிப்பதாக இருந்தால், CRUD முறையே வேகமானது மற்றும் மலிவானது. உங்களுக்கு காலவரிசை வினவல்கள் (temporal queries), கடுமையான தணிக்கைத்தன்மை அல்லது தேவைப்படும்போது ரீட் மாடல்களை மீண்டும் உருவாக்கும் திறன் தேவைப்பட்டால் மட்டுமே, events முறையைப் பயன்படுத்துவது அர்த்தமுள்ளதாகும். நீங்கள் எதற்கான தீர்வைத் தேடுகிறீர்கள் என்பதை உறுதிப்படுத்திய பின்பே இதில் இறங்கவும்.

மேம்படுத்துவதற்கு முன் அளவிடுங்கள். சாதாரண வன்பொருளில் இயங்கும் நவீன PostgreSQL, ஒரு எளிய append-only அட்டவணை மூலம் ஒரு வினாடிக்கு ஆயிரக்கணக்கான நிகழ்வுகளை உள்வாங்க முடியும். உங்கள் கண்காணிப்பு (monitoring) முறைகள் எளிய தீர்வுகளைக் கூடப் பயன்படுத்தவில்லை என்று நிரூபிக்கும் வரை, உங்கள் event store-ஐ ஷார்ட் (shard) செய்யவோ அல்லது சிக்கலான பகிர்வு முறைகளை (partitioning schemes) அறிமுகப்படுத்தவோ வேண்டாம். நீங்கள் வினவ வேண்டிய புலங்களுக்கு (fields) குறியீடுகளை (index) உருவாக்குங்கள். append-only வேலைப்பளுவிற்கு ஏற்ப autovacuum-ஐச் சரிசெய்யுங்கள். அதன் பிறகு மீண்டும் அளவிடுங்கள்.

Test everything. Unit test your event handlers. Integration test the append path. Most importantly, test failure scenarios. What happens when two nodes append to the same stream simultaneously? What happens when a projection worker crashes mid-batch? Write tests that verify your optimistic concurrency and your at-least-once delivery guarantees.

Monitor in production. The events table will grow. Unlike a normalized schema where updates keep row counts flat, event sourcing is intentionally additive. Track table size, disk I/O, and the lag between your write model and your read model projections. Set alerts on projection lag before your users notice stale data.

Automate manual tasks. Manual schema changes, manual projection rebuilds, and manual event replay are ticking time bombs. Script your migration strategy. If you evolve an event schema, automate the upcasting or transformation so that old events can be replayed through new logic without human intervention at midnight.

Document your choices. Write down why specific streams exist, what each event type means, and when the team should choose CRUD over events. Event sourcing introduces cognitive load. Good documentation prevents a new engineer from guessing wrong and appending malformed events to a critical stream.

Traps That Waste Months

Event sourcing has a way of sounding elegant in a diagram and painful in production. Watch for these traps.

Underestimating complexity. Replaying events to rebuild state is conceptually simple. Managing idempotency, snapshotting for performance, and compensating transactions across aggregates is not. Break your system into small pieces. Solve one stream at a time.

Over-engineering. Do not provision a multi-node Kafka cluster because you imagine your event volume will one day require it. Postgres can carry you surprisingly far. Introduce new infrastructure only when you have a measured bottleneck that you cannot fix within your current setup.

Ignoring technical debt. Old event schemas linger forever. If you change your OrderCreated payload, you still have ten million historical events in the old shape. Track this debt. Plan backward-compatible readers or migration scripts. Do not let the burden of legacy events slow every new feature.

Choosing tools the team cannot run. The best architecture fails if only one person understands it. If your team knows Postgres and SQL, start there. If you introduce a specialized event store, make sure you have the operational expertise to debug it at two in the morning.

A Practical Starting Point

If this approach fits your problem, do not wait for a five-quarter rewrite. Start this week.

Audit your current systems. Find a place where an audit trail would solve real pain. Maybe it is an order state machine that currently maintains a single status column. Perhaps it is a financial ledger where balance corrections require manual database patches. Pick one gap where overwriting state has hurt you.

Then pick one small improvement you can make today. Create one event table. Model one stream. Write one projection that builds a read model from those events. Deploy it behind a feature flag. Watch it handle real traffic.

Event sourcing with PostgreSQL is not magic. It is a practical tool for teams that need to know not just where things are, but how they got there. Build slowly, measure honestly, and let your actual requirements guide the architecture.

Source: https://dev.to/therizwansaleem/event-sourcing-with-postgresql-using-the-database-as-an-event-store-2kd4