Postgres ਸਕੀਮਾ ਡਿਜ਼ਾਇਨ ਯੋਜਨਾ ਮੋਡ ਤੁਹਾਨੂੰ entities, constraints, indexes ਅਤੇ migrations ਨੂੰ ਕੋਡ ਜਨਰੇਸ਼ਨ ਤੋਂ ਪਹਿਲਾਂ ਨਿਰਧਾਰਤ ਕਰਨ ਵਿੱਚ ਮਦਦ ਕਰਦਾ ਹੈ, ਜਿਸ ਨਾਲ ਬਾਅਦ ਵਿੱਚ ਦੁਬਾਰਾ ਲਿਖਣ ਦੀ ਲੋੜ ਘੱਟ ਹੋ ਜਾਂਦੀ ਹੈ।

ਜੇ ਤੁਸੀਂ ਡੇਟਾਬੇਸ ਦਾ ਆਕਾਰ ਸਪਸ਼ਟ ਹੋਣ ਤੋਂ ਪਹਿਲਾਂ endpoints ਅਤੇ ਮਾਡਲ ਬਣਾਉਂਦੇ ਹੋ, ਤਾਂ ਅਕਸਰ ਤੁਹਾਨੂੰ ਉਹੀ ਫੀਚਰ ਦੋ ਵਾਰੀ ਦੁਬਾਰਾ ਲਿਖਣੇ ਪੈਂਦੇ ਹਨ। ਐਪ ਡੈਮੋ ਲਈ ਚੱਲਦੀ ਹੈ, ਫਿਰ ਅਸਲ ਡੇਟਾ ਅਤੇ ਕਿਨਾਰੇ ਦੇ ਕੇਸ ਆਉਂਦੇ ਹਨ ਅਤੇ ਹਰ ਚੀਜ਼ ਨਾਜ਼ੁਕ ਮਹਿਸੂਸ ਹੁੰਦੀ ਹੈ।
ਜ਼ਿਆਦਾਤਰ ਦੁਬਾਰੇ ਲਿਖਾਈਆਂ ਤਿੰਨ ਅਣੁਮਾਨਯੋਗ ਸਮੱਸਿਆਵਾਂ ਕਾਰਨ ਹੁੰਦੀਆਂ ਹਨ:
ਇਨ੍ਹਾਂ ਵਿੱਚੋਂ ਹਰ ਇੱਕ ਬਦਲਾਅ ਲੈ ਕੇ ਆਉਂਦਾ ਹੈ ਜੋ ਕੋਡ, ਟੈਸਟ ਅਤੇ ਕਲਾਇਂਟ ਐਪਸ ਤੱਕ ਫੈਲਦਾ ਹੈ।
Postgres ਸਕੀਮਾ ਦੀ ਯੋਜਨਾ ਬਣਾਉਣ ਦਾ ਮਤਲਬ ਹੈ ਪਹਿਲਾਂ ਡੇਟਾ ਦਾ ਠੀਕ ਤੌਰ ਤੇ ਨਿਰਧਾਰਨ ਕਰਨਾ, ਫਿਰ ਉਹ ਕੋਡ ਜਨਰੇਟ ਕਰਨਾ ਜੋ ਉਸ ਨਾਲ ਮਿਲਦਾ ਹੋਵੇ। ਅਮਲ ਵਿੱਚ, ਇਹ entities, ਰਿਸ਼ਤੇ, ਅਤੇ ਉਹ ਕੁਝ ਕੁਵੀਰੀਆਂ ਲਿਖਣ ਵਰਗਾ ਹੁੰਦਾ ਹੈ ਜੋ ਮੈਟਰ ਕਰਦੀਆਂ ਹਨ, ਫਿਰ constraints, indexes ਅਤੇ migration ਰਣਨੀਤੀ ਚੁਣਨੀ ਹੁੰਦੀ ਹੈ ਪਹਿਲਾਂ ਕਿ ਕੋਈ ਟੂਲ tables ਅਤੇ CRUD scaffold ਕਰੇ।
ਇਹ ਵਕਤ ਵੀ ਜ਼ਿਆਦਾ ਮਹੱਤਵਪੂਰਨ ਹੁੰਦਾ ਹੈ ਜਦੋਂ ਤੁਸੀਂ Koder.ai ਵਰਗੇ vibe-coding ਪਲੇਟਫਾਰਮ ਦੀ ਵਰਤੋਂ ਕਰਦੇ ਹੋ, ਜਿੱਥੇ ਤੁਸੀਂ ਬਹੁਤ ਸਾਰਾ ਕੋਡ ਤੇਜ਼ੀ ਨਾਲ ਜਨਰੇਟ ਕਰ ਸਕਦੇ ਹੋ। ਤੇਜ਼ ਜਨਰੇਸ਼ਨ ਵਧੀਆ ਹੈ, ਪਰ schema ਜਿਹੜਾ ਸਥਿਰ ਹੋਵੇ ਉਸ ਵੇਲੇ ਇਹ ਜ਼ਿਆਦਾ ਭਰੋਸੇਯੋਗ ਹੁੰਦਾ ਹੈ। ਤੁਹਾਡੇ ਜਨਰੇਟ ਕੀਤੇ ਮਾਡਲ ਅਤੇ endpoints ਨੂੰ ਬਾਅਦ ਵਿੱਚ ਘੱਟ ਸੋਧਾਂ ਦੀ ਲੋੜ ਪਏਗੀ।
ਜੇ ਤੁਸੀਂ ਯੋਜਨਾ ਛੱਡ ਦਿੰਦੇ ਹੋ ਤਾਂ ਆਮ ਤੌਰ ਤੇ ਇਹ ਗਲਤੀਆਂ ਹੁੰਦੀਆਂ ਹਨ:
ਇੱਕ ਚੰਗੀ schema ਯੋਜਨਾ ਸਧਾਰਨ ਹੁੰਦੀ ਹੈ: entities ਦੀ ਸਾਦੀ ਭਾਸ਼ਾ ਵਾਲੀ ਵਿਆਖਿਆ, ਟੇਬਲਾਂ ਅਤੇ ਕਾਲਮਾਂ ਦਾ ਡਰਾਫਟ, ਮੁੱਖ constraints ਅਤੇ indexes, ਅਤੇ ਇੱਕ migration ਰਣਨੀਤੀ ਜੋ ਪ੍ਰੋਡਕਟ ਦੇ ਵਧਣ ਨਾਲ ਸੁਰੱਖਿਅਤ ਢੰਗ ਨਾਲ ਚੀਜ਼ਾਂ ਬਦਲਣ ਦੇ ਯੋਗ ਹੋਵੇ।
Schema ਯੋਜਨਾ ਸਭ ਤੋਂ ਵਧੀਆ ਇਸ ਵੇਲੇ ਕੰਮ ਕਰਦੀ ਹੈ ਜਦੋਂ ਤੁਸੀਂ ਸ਼ੁਰੂਆਤ ਵੱਧ ਤੋਂ ਵੱਧ ਇਸ ਗੱਲ ਨਾਲ ਕਰੋ ਕਿ ਐਪ ਨੂੰ ਕੀ ਯਾਦ ਰੱਖਣਾ ਹੋਵੇ ਅਤੇ ਲੋਕ ਉਸ ਡੇਟੇ ਨਾਲ ਕੀ ਕਰ ਸਕਣ। 2–3 ਸਧਾਰਨ ਵਾਕਾਂ ਵਿੱਚ ਲਕਸ਼ਯ ਲਿਖੋ। ਜੇ ਤੁਸੀਂ ਇਸਨੂੰ ਆਸਾਨੀ ਨਾਲ ਸਮਝਾ ਨਹੀਂ ਸਕਦੇ, ਤਾਂ ਸ਼ਾਇਦ ਤੁਸੀਂ ਅਣਜਰੂਰੀ ਟੇਬਲ ਬਣਾਉਣਗੇ।
ਅਗਲੇ ਕਦਮ ਵਿੱਚ ਉਹ ਕਾਰਵਾਈਆਂ ਲਿਖੋ ਜੋ ਡੇਟਾ ਬਣਾਉਂਦੀਆਂ ਜਾਂ ਬਦਲਦੀਆਂ ਹਨ। ਇਹ ਕਾਰਵਾਈਆਂ ਹੀ ਅਸਲ ਸਰੋਤ ਹਨ ਤੁਹਾਡੇ ਰੋਜ਼ਾਂ ਲਈ, ਅਤੇ ਇਹ ਦਿਖਾਉਂਦੀਆਂ ਹਨ ਕਿ ਕੀ-ਕਿ ਵੈਧ ਹੋਣਾ ਚਾਹੀਦਾ ਹੈ। ਸਿਰਫ਼ ਨਾਂਵਾਂ ਦੀ ਸੋਚੋ ਨਾ ਕਰਕੇ ਕਿਰਿਆਵਾਂ (verbs) `'ਤੇ ਧਿਆਨ ਦਿਓ।
ਉਦਾਹਰਣ ਵਜੋਂ, ਇੱਕ booking ਐਪ ਨੂੰ booking ਬਣਾਉਣਾ, ਉਸ ਨੂੰ reschedule ਕਰਨਾ, cancel ਕਰਨਾ, refund ਕਰਨਾ ਅਤੇ customer ਨੂੰ message ਭੇਜਣਾ ਲੋੜੀਂਦਾ ਹੋ ਸਕਦਾ ਹੈ। ਇਹ verbs ਜਲਦੀ ਇਹ ਸجھਾਉਂਦੇ ਹਨ ਕਿ ਕੀ ਸੰਭਾਲਣਾ ਹੈ (time slots, status changes, money amounts) ਪਹਿਲਾਂ ਹੀ ਿਟੇਬਲ ਨਾਮ ਰੱਖਣ ਤੋਂ ਪਹਿਲਾਂ।
ਆਪਣੇ read paths ਵੀ ਕੈਪਚਰ ਕਰੋ, ਕਿਉਂਕਿ reads ਅਗਲੇ ਰਚਨਾ ਅਤੇ indexing ਨੂੰ ਚਲਾਉਂਦੇ ਹਨ। ਉਹ screens ਜਾਂ reports ਲਿਖੋ ਜੋ ਲੋਕ ਅਸਲ ਵਿੱਚ ਵਰਤਣਗੇ ਅਤੇ ਉਹ ਕਿਵੇਂ ਡੇਟਾ ਨੂੰ slice ਕਰਦੇ ਹਨ: “My bookings” ਤਰੀਕਾਬੱਧ ਕਰਕੇ date ਦੇ ਨੇੜੇ ਅਤੇ status ਨਾਲ filter ਕਰਕੇ, admin search by customer name ਜਾਂ booking reference, ਰੋਜ਼ਾਨਾ ਦੀ revenue by location, ਅਤੇ ਇਹ ਵੇਖਣ ਵਾਲਾ audit view ਕਿ ਕਿਸ ਨੇ ਕੀ ਅਤੇ ਕਦੋਂ ਬਦਲਿਆ।
ਆਖ਼ਰ ਵਿੱਚ, ਉਹ non-functional ਲੋੜਾਂ ਨੋਟ ਕਰੋ ਜੋ schema ਚੋਣਾਂ ਨੂੰ ਪ੍ਰਭਾਵਿਤ ਕਰਦੀਆਂ ਹਨ, ਜਿਵੇਂ audit history, soft deletes, multi-tenant ਅਲੱਗ-ਪਛਾਣ, ਜਾਂ privacy ਨਿਯਮ (ਉਦਾਹਰਣ ਲਈ, contact details ਨੂੰ ਕੰਨੂੰ ਕੌਣ ਵੇਖ ਸਕਦਾ ਹੈ ਉੱਤੇ ਸੀਮਾ)।
ਜੇ ਤੁਸੀਂ ਇਸ ਤੋਂ ਬਾਅਦ ਕੋਡ ਜਨਰੇਟ ਕਰਨ ਦੀ ਯੋਜਨਾ ਬਣਾਉਂਦੇ ਹੋ, ਤਾਂ ਇਹ ਨੋਟਜ਼ ਮਜ਼ਬੂਤ ਪ੍ਰਾਪਰੰਪ ਬਣ ਜਾਂਦੇ ਹਨ। ਇਹ ਦੱਸਦੇ ਹਨ ਕੀ ਲੋੜੀਂਦਾ ਹੈ, ਕੀ ਬਦਲ ਸਕਦਾ ਹੈ, ਅਤੇ ਕੀ searchable ਹੋਣਾ ਚਾਹੀਦਾ ਹੈ। ਜੇ ਤੁਸੀਂ Koder.ai ਵਰਤ ਰਹੇ ਹੋ, ਤਾਂ ਕੁਝ ਵੀ ਜਨਰੇਟ ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ ਇਹ ਲਿਖਣਾ Planning Mode ਨੂੰ ਕਾਫੀ ਪ੍ਰਭਾਵਸ਼ালী ਬਣਾਉਂਦਾ ਹੈ ਕਿਉਂਕਿ ਪਲੇਟਫਾਰਮ ਅਨੁਮਾਨਾਂ ਦੇ ਥਾਂ ਅਸਲ ਲੋੜਾਂ ਤੋਂ ਕੰਮ ਕਰ ਰਿਹਾ ਹੁੰਦਾ ਹੈ।
ਟੇਬਲ ਛੁਹਣ ਤੋਂ ਪਹਿਲਾਂ, ਲਿਖੋ ਕਿ ਤੁਹਾਡੀ ਐਪ ਕੀ ਸਟੋਰ ਕਰਦੀ ਹੈ। ਉਹ nouns ਲਿਸਟ ਕਰੋ ਜੋ ਤੁਸੀਂ ਵਾਰ-ਵਾਰ ਦੁਹਰਾਉਂਦੇ ਹੋ: user, project, message, invoice, subscription, file, comment। ਹਰ noun ਇੱਕ candidate entity ਹੈ।
ਫਿਰ ਹਰ entity ਲਈ ਇੱਕ ਵਾਕ ਦਿਓ ਜੋ ਜਵਾਬ ਦੇਵੇ: ਇਹ ਕੀ ਹੈ, ਅਤੇ ਇਹ ਕਿਉਂ ਮੌਜੂਦ ਹੈ? ਉਦਾਹਰਣ: “A Project is a workspace a user creates to group work and invite others.” ਇਹ vague ਟੇਬਲਾਂ ਜਿਵੇਂ data, items, ਜਾਂ misc ਬਣਨ ਤੋਂ ਰੋਕਦਾ ਹੈ।
Ownership ਅਗਲਾ ਵੱਡਾ ਫੈਸਲਾ ਹੈ, ਅਤੇ ਇਹ ਲਗਭਗ ਹਰ query ਨੂੰ ਪ੍ਰਭਾਵਿਤ ਕਰਦਾ ਹੈ। ਹਰ entity ਲਈ ਫੈਸਲਾ ਕਰੋ:
ਹੁਣ ਫ਼ੈਸਲਾ ਕਰੋ ਕਿ ਤੁਹਾਡੇ ਰਿਕਾਰਡਾਂ ਦੀ ਪਛਾਣ ਕਿਵੇਂ ਕੀਤੀ ਜਾਵੇਗੀ। UUID ਉਨ੍ਹਾਂ ਲਈ ਵਧੀਆ ਹਨ ਜਦੋਂ ਰਿਕਾਰਡ ਕਈ ਥਾਵਾਂ (ਵੇਬ, ਮੋਬਾਈਲ, background jobs) ਤੋਂ ਬਣ ਸਕਦੇ ਹਨ ਜਾਂ ਤੁਸੀਂ predictable IDs ਨਹੀਂ ਚਾਹੁੰਦੇ। bigint IDs ਛੋਟੇ ਅਤੇ ਤੇਜ਼ ਹੁੰਦੇ ਹਨ। ਜੇ ਤੁਹਾਨੂੰ human-friendly identifier ਚਾਹੀਦਾ ਹੈ, ਤਾਂ ਉਹ ਨੂੰ ਵੱਖਰਾ ਰੱਖੋ (ਉਦਾਹਰਣ ਲਈ, ਇੱਕ ਛੋਟਾ project_code ਜੋ account ਵਿੱਚ unique ਹੋ) ਬਜਾਏ primary key ਬਣਾਉਣ ਦੇ।
ਅਖ਼ਿਰ ਵਿੱਚ, ਰਿਸ਼ਤੇ ਸ਼ਬਦਾਂ ਵਿੱਚ ਬਿਆਨ ਕਰੋ ਪਹਿਲਾਂ ਕਿ ਤੁਸੀਂ ਕਿਸੇ ਚੀਜ਼ ਦਾ diagram ਬਣਾਉਂਦੇ ਹੋ: ਇੱਕ user ਦੇ ਕੋਲ ਬਹੁਤ ਸਾਰੇ projects ਹੋ ਸਕਦੇ ਹਨ, ਇੱਕ project ਦੇ ਕੋਲ ਬਹੁਤ ਸਾਰੇ messages ਹਨ, ਅਤੇ users ਕਈ projects ਦਾ ਹਿੱਸਾ ਹੋ ਸਕਦੇ ਹਨ। ਹਰ link ਨੂੰ required ਜਾਂ optional ਨਿਸ਼ਾਨ ਲਗਾਓ, ਜਿਵੇਂ “a message must belong to a project” ਵਿਰੁੱਧ “an invoice may belong to a project.” ਇਹ ਵਾਕ ਅਗਲੇ ਸਮੇਂ code generation ਲਈ ਤੁਹਾਡੀ ਸਚਾਈ ਦਾ ਸਰੋਤ ਬਣ ਜਾਂਦੇ ਹਨ।
ਜਦੋਂ entities ਸਪਸ਼ਟ ਹੋ ਜਾਣ, ਹਰ ਇੱਕ ਨੂੰ ਇੱਕ table ਵਿੱਚ ਬਦਲੋ ਜਿਸਦੇ ਕਾਲਮ ਉਹ ਅਸਲ ਤਥਾਂ ਨੂੰ ਮਿਲਦੇ ਹਨ ਜੋ ਤੁਹਾਨੂੰ ਸੰਭਾਲਣੀਆਂ ਹਨ।
ਸਰਲਾ ਨਾਮ ਅਤੇ types ਨਾਲ ਸ਼ੁਰੂ ਕਰੋ ਜੋ ਤੁਸੀਂ ਲੰਬੇ ਸਮੇਂ ਲਈ ਵਰਤ ਸਕੋ। ਲਗਾਤਾਰ ਪੈਟਰਨ ਚੁਣੋ: snake_case column names, ਇੱਕੋ ਹੀ ধারণਾ ਲਈ ਇੱਕੋ type, ਅਤੇ predictable primary keys। timestamps ਲਈ, timestamptz ਪਸੰਦ ਕਰੋ ਤਾਂ ਕਿ time zones ਨੇਹੁੰ ਤੁਹਾਨੂੰ ਹੈਰਾਨ ਨ ਕਰਦੇ। ਪੈਸੇ ਲਈ numeric(12,2) (ਜਾਂ cents ਨੂੰ integer ਵਜੋਂ ਰੱਖੋ) ਵਰਤੋ, float ਤੋਂ ਬਚੋ।
status ਫੀਲਡਾਂ ਲਈ, Postgres enum ਜਾਂ text ਕਾਲਮ ਨਾਲ CHECK constraint ਵਰਤੋ ਤਾਂ ਕਿ allowed values ਨਿਯੰਤਰਤ ਰਹਿਣ।
ਕੀ required ਹੈ ਅਤੇ ਕੀ optional ਹੈ, ਇਸਨੂੰ NOT NULL ਵਿੱਚ translate ਕਰੋ। ਜੇ ਇੱਕ value ਰਿਕਾਰਡ ਲਈ ਲਾਜ਼ਮੀ ਹੈ, ਤਾਂ ਉਸਨੂੰ required ਬਣਾਓ। ਜੇ ਇਹ ਸੱਚਮੁੱਚ unknown ਜਾਂ lagu nahi ਹੁੰਦੀ, ਤਾਂ nulls ਦੀ ਆਗਿਆ ਦਿਓ।
ਇੱਕ ਪ੍ਰਯੋਗਿਕ default column ਸੈਟ ਜੋ ਯੋਜਨਾ ਲਈ ਹੈ:
id (uuid ਜਾਂ bigint, ਇੱਕ ਆਪਣੀ ਚੋਣ ਕਰੋ ਅਤੇ ਲਗਾਤਾਰ ਰਹੋ)created_at ਅਤੇ updated_atdeleted_at ਸਿਰਫ਼ ਜੇ ਤੁਹਾਨੂੰ ਸਚਮੁਚ soft deletes ਅਤੇ restore ਦੀ ਲੋੜ ਹੈcreated_by ਜਦੋਂ ਤੁਹਾਨੂੰ ਦਰਸਾਇਆ ਹੋਏ audit trail ਦੀ ਲੋੜ ਹੋਵੇMany-to-many ਰਿਸ਼ਤੇ ਆਮ ਤੌਰ ਤੇ join tables ਬਣ ਜਾਣੇ ਚਾਹੀਦੇ ਹਨ। ਉਦਾਹਰਣ ਵਜੋਂ, ਜੇ ਮੁੱਖ users ਇੱਕ app 'ਤੇ ਸਹਿਯੋਗ ਕਰ ਸਕਦੇ ਹਨ, ਤਾਂ app_members ਬਣਾਓ ਜਿਸ ਵਿੱਚ app_id ਅਤੇ user_id ਹੋਣ ਅਤੇ ਜੋੜੇ ਤੇ uniqueness enforce ਕਰੋ ਤਾਂ ਕਿ duplicates ਨਾ ਆ ਸਕਣ।
ਇਤਿਹਾਸ ਬਾਰੇ ਸੋਚੋ shuru ਤੋਂ ਹੀ। ਜੇ ਤੁਹਾਨੂੰ versioning ਦੀ ਲੋੜ ਪਤਾ ਹੈ, ਤਾਂ ਇੱਕ immutable table ਜਿਵੇਂ app_snapshots ਯੋਜਨਾ ਕਰੋ, ਜਿੱਥੇ ਹਰ row ਇੱਕ saved version ਹੈ ਜੋ apps ਨਾਲ app_id ਰਾਹੀਂ linked ਅਤੇ created_at ਨਾਲ stamp ਕੀਤੀ ਜਾਂਦੀ ਹੈ।
Constraints ਤੁਹਾਡੇ schema ਦੀਆਂ ਰੱਖਿਆਆਂ ਹਨ। ਫੈਸਲਾ ਕਰੋ ਕਿ ਕਿਹੜੇ ਨਿਯਮ ਹਰ ਹਾਲਤ ਵਿੱਚ ਸਹੀ ਹੋਣੇ ਚਾਹੀਦੇ ਹਨ, ਭਾਵੇਂ ਕੋਈ ਵੀ ਸਰਵਿਸ, ਸਕ੍ਰਿਪਟ ਜਾਂ admin ਟੂਲ ਡੇਟਾਬੇਸ ਨੂੰ ਛੂਹੇ।
ਪਹਿਲਾਂ identity ਅਤੇ relationships ਨਾਲ ਸ਼ੁਰੂ ਕਰੋ। ਹਰ table ਨੂੰ primary key ਚਾਹੀਦੀ ਹੈ, ਅਤੇ ਕਿਸੇ ਵੀ “belongs to” ਫੀਲਡ ਲਈ ਸੱਚਾ foreign key ਹੋਣਾ ਚਾਹੀਦਾ ਹੈ, ਨਾ ਕਿ ਸਿਰਫ਼ ਇੱਕ integer ਜੋ ਤੁਸੀਂ ਉਮੀਦ ਕਰਦੇ ਹੋ ਕਿ ਮੇਲ ਖਾਏਗਾ।
ਫਿਰ uniqueness ਜੋੜੋ ਜਿੱਥੇ duplicates ਵਾਸਤੇ ਵਾਸਤਵਿਕ ਨੁਕਸਾਨ ਹੋਵੇ, ਜਿਵੇਂ ਦੋ accounts ਇੱਕੋ email ਨਾਲ ਜਾਂ ਦੋ line items ਇੱਕੋ (order_id, product_id) ਨਾਲ।
ਉੱਚ-ਮ hull constraints ਜੋ ਸ਼ੁਰੂ ਤੋਂ ਯੋਜਨਾ ਕਰਨੇ ਚਾਹੀਦੇ ਹਨ:
amount >= 0, status IN ('draft','paid','canceled'), ਜਾਂ rating BETWEEN 1 AND 5.Cascade ਬਿਹੇਵਿਅਰ ਉਹ ਥਾਂ ਹੈ ਜਿੱਥੇ ਯੋਜਨਾ ਤੁਹਾਨੂੰ ਬਾਅਦ ਵਿੱਚ ਬਚਾਉਂਦੀ ਹੈ। ਪੁੱਛੋ ਕਿ ਲੋਕ ਅਸਲ ਵਿੱਚ ਕੀ ਉਮੀਦ ਕਰਦੇ ਹਨ। ਜੇ ਇੱਕ customer ਮਿਟ ਜਾਂਦਾ ਹੈ, ਤਾਂ ਆਮ ਤੌਰ 'ਤੇ ਉਹਨਾਂ ਦੇ orders ਗਾਇਬ ਨਹੀਂ ਹੋਣੇ ਚਾਹੀਦੇ। ਇਹ RESTRICT ਨੂੰ ਦਰਸਾਉਂਦਾ ਹੈ ਅਤੇ ਇਤਿਹਾਸ ਰੱਖਣ ਲਈ ਮਦਦਗਾਰ ਹੈ। ਇੰਝ dependents data ਜਿਵੇਂ order line items ਲਈ, order ਤੋਂ items 'ਤੇ cascading ਮੱਤਲਬ ਰੱਖ ਸਕਦੀ ਹੈ ਕਿਉਂਕਿ items ਬਿਨਾਂ parent ਦੇ ਕੋਈ ਮਤਲਬ ਨਹੀਂ ਰੱਖਦੇ।
ਜਦੋਂ ਤੁਸੀਂ ਮਾਡਲ ਅਤੇ endpoints ਜਨਰੇਟ ਕਰਦੇ ਹੋ, ਇਹ constraints ਸਪਸ਼ਟ ਮੰਗਾਂ ਬਣ ਜਾਂਦੀਆਂ ਹਨ: ਕਿਹੜੇ errors ਸੰਭਾਲਣੇ ਹਨ, ਕਿਹੜੇ ਫੀਲਡ ਲਾਜ਼ਮੀ ਹਨ, ਅਤੇ ਕਿਹੜੀਆਂ edge cases ਡਿਜ਼ਾਇਨ ਵੱਲੋਂ ਅਸੰਭਵ ਹਨ।
Indexes ਇੱਕ ਸਵਾਲ ਜਵਾਬ ਦੇਣੇ ਚਾਹੁੰਦੇ ਹਨ: ਕੀ ਗੱਲ ਉਪਭੋਗਤਾਵਾਂ ਲਈ ਸੱਚਮੁਚ ਤੇਜ਼ ਹੋਣੀ ਚਾਹੀਦੀ ਹੈ।
ਸ਼ੁਰੂ ਕਰੋ ਉਹ screens ਅਤੇ API calls ਨਾਲ ਜੋ ਤੁਸੀਂ ਪਹਿਲਾਂ ship ਕਰਨ ਦੀ ਉਮੀਦ ਰੱਖਦੇ ਹੋ। ਇੱਕ list ਪੇਜ ਜੋ status ਦੇ ਨਾਲ filter ਕਰਦਾ ਅਤੇ newest ਨਾਲ sort ਕਰਦਾ ਹੈ, ਉਸਦੀ ਲੋੜ ਕਿਸੇ detail page ਦੀ ਲੋੜ ਤੋਂ ਵੱਖਰੀ ਹੁੰਦੀ ਹੈ ਜੋ related records ਲੋਡ ਕਰਦਾ ਹੈ।
ਕੋਈ ਵੀ index ਚੁਣਨ ਤੋਂ ਪਹਿਲਾਂ 5–10 query patterns plain English ਵਿੱਚ ਲਿਖੋ। ਉਦਾਹਰਣ: “Show my invoices for the last 30 days, filter by paid/unpaid, sort by created_at,” ਜਾਂ “Open a project and list its tasks by due_date.” ਇਹ index ਚੋਣਾਂ ਨੂੰ ਅਸਲ ਵਰਤੋਂ 'ਤੇ ਧਰੋੜਾ ਰੱਖਦਾ ਹੈ।
ਚੰਗਾ ਪਹਿਲਾ index ਸੈਟ ਆਮ ਤੌਰ 'ਤੇ foreign key ਕਾਲਮ ਜੋ joins ਲਈ ਵਰਤੇ ਜਾਂਦੇ ਹਨ, common filter ਕਾਲਮ (ਜਿਵੇਂ status, user_id, created_at), ਅਤੇ ਇੱਕ ਜਾਂ ਦੋ composite indexes ਲਈ ਹੋਵੇਗਾ ਜੋ stable multi-filter queries ਲਈ ਲਾਭਦਾਇਕ ਹਨ, ਜਿਵੇਂ (account_id, created_at) ਜਦੋਂ ਤੁਸੀਂ ਹਮੇਸ਼ਾ account_id ਨਾਲ filter ਕਰਦੇ ਹੋ ਅਤੇ ਫਿਰ time ਨਾਲ sort ਕਰਦੇ ਹੋ।
Composite index ਦੀ order ਮਹੱਤਵਪੂਰਨ ਹੁੰਦੀ ਹੈ। ਸਭ ਤੋਂ ਪਹਿਲਾਂ ਉਹ column ਰੱਖੋ ਜੋ ਤੁਸੀਂ ਸਭ ਤੋਂ ਵੱਧ filter ਕਰਦੇ ਹੋ (ਅਤੇ ਜ਼ਿਆਦਾ selective ਹੈ)। ਜੇ ਤੁਸੀਂ ਹਰ request 'ਤੇ tenant_id ਨਾਲ filter ਕਰਦੇ ਹੋ, ਤਾਂ ਉਹ ਬਹੁਤ ਸਾਰੇ indexes ਦੇ ਆਗੇ ਹੋਣਾ ਚਾਹੀਦਾ ਹੈ।
ਹਰ ਚੀਜ਼ ਤੇ index ਨਾ ਲਗਾਓ “ਸ਼ਾਇਦ” ਲਈ। ਹਰ index INSERT ਅਤੇ UPDATE 'ਤੇ ਕੰਮ ਵਧਾਉਂਦਾ ਹੈ, ਅਤੇ ਇਹ ਇਕ ਕਦੇ-ਕਦੇ rare query ਦੀ ਥੋੜੀ ਤੇਜ਼ੀ ਨਾਲੋਂ ਜ਼ਿਆਦਾ ਨੁਕਸਾਨ ਕਰ ਸਕਦਾ ਹੈ।
text search ਨੂੰ ਅਲੱਗ ਯੋਜਨਾ ਬਣਾਓ। ਜੇ ਤੁਹਾਨੂੰ ਸਿਰਫ਼ simple “contains” matching ਦੀ ਲੋੜ ਹੈ, ਤਾਂ ਸ਼ੁਰੂ ਵਿੱਚ ILIKE ਕਾਫੀ ਹੋ ਸਕਦਾ ਹੈ। ਜੇ search ਮੂਲ ਹੈ, ਤਾਂ early ਤੇ tsvector ਵਰਗਾ full-text search ਯੋਜਨਾ ਕਰੋ ਤਾਂ ਕਿ ਬਾਅਦ ਵਿੱਚ ਦੁਬਾਰਾ ਡਿਜ਼ਾਈਨ ਨਾ ਕਰਨਾ ਪਵੇ।
ਇੱਕ schema "done" ਨਹੀਂ ਹੁੰਦੀ ਜਦੋਂ ਤੁਸੀਂ ਪਹਿਲੀਆਂ ਟੇਬਲਾਂ ਬਣਾਉਂਦੇ ਹੋ। ਇਹ ਹਰ ਵਾਰ ਬਦਲਦੀ ਹੈ ਜਦੋਂ ਤੁਸੀਂ ਇੱਕ ਫੀਚਰ ਜੋੜਦੇ ਹੋ, ਇੱਕ ਗਲਤੀ ਠੀਕ ਕਰਦੇ ਹੋ, ਜਾਂ ਆਪਣੇ ਡੇਟਾ ਬਾਰੇ ਹੋਰ ਸਿੱਖਦੇ ਹੋ। ਜੇ ਤੁਸੀਂ migration ਰਣਨੀਤੀ ਪਹਿਲਾਂ ਤੋਂ ਫੈਸਲਾ ਕਰ ਲਵੋ, ਤਾਂ ਤੁਸੀਂ ਕੋਡ ਜਨਰੇਸ਼ਨ ਤੋਂ ਬਾਅਦ ਦਰਦਨਾਕ ਦੁਬਾਰੇ ਲਿਖਣ ਤੋਂ ਬਚ ਸਕਦੇ ਹੋ।
ਸਰਲ ਨਿਯਮ ਰੱਖੋ: ਡੇਟਾਬੇਸ ਨੂੰ ਛੋਟੇ-چھੋਟੇ ਕਦਮਾਂ ਵਿੱਚ ਬਦਲੋ, ਇੱਕ ਫੀਚਰ ਇੱਕ ਵਾਰੀ। ਹਰ migration review ਕਰਨ ਯੋਗ ਅਤੇ ਹਰ environment ਵਿੱਚ ਸੁਰੱਖਿਅਤ ਰੂਪ ਵਿੱਚ ਚਲਾਈ ਜਾ ਸਕਣੀ ਚਾਹੀਦੀ ਹੈ।
ਜ਼ਿਆਦਾਤਰ ਟੁੱਟਣ rename ਜਾਂ remove columns ਜਾਂ types ਬਦਲਣ ਤੋਂ ਆਉਂਦਾ ਹੈ। ਸਾਰਾ ਕੁਝ ਇਕ ਵਾਰੀ ਕਰਨ ਦੀ ਬਜਾਏ, ਇੱਕ ਸੁਰੱਖਿਅਤ ਰਾਹ ਯੋਜਨਾ ਕਰੋ:
ਇਹ ਕਦਮ ਜ਼ਿਆਦਾ ਹੋ ਸਕਦੇ ਹਨ, ਪਰ ਅਸਲ ਵਿੱਚ ਇਹ ਤੇਜ਼ ਹਨ ਕਿਉਂਕਿ ਇਹ outages ਅਤੇ ਐਮਰਜੈਂਸੀ patches ਨੂੰ ਘੱਟ ਕਰਦੇ ਹਨ।
Seed data migrations ਦਾ ਹਿੱਸਾ ਵੀ ਹੁੰਦੀ ਹੈ। ਫੈਸਲਾ ਕਰੋ ਕਿ ਕਿਹੜੀਆਂ reference tables "ਹਮੇਸ਼ਾਂ ਹਨ" (roles, statuses, countries, plan types) ਅਤੇ ਉਨ੍ਹਾਂ ਨੂੰ predictable ਬਣਾਓ। ਇਹਨਾਂ tables ਲਈ inserts ਅਤੇ updates ਨੂੰ dedicated migrations ਵਿੱਚ ਰੱਖੋ ਤਾਂ ਕਿ ਹਰ ਡਿਵੈਲਪਰ ਅਤੇ ਹਰ deploy ਨੂੰ ਇੱਕੋ ਨਤੀਜੇ ਮਿਲਣ।
ਸ਼ੁਰੂ ਤੋਂ ਹੀ ਉਮੀਦਾਂ ਸੈੱਟ ਕਰੋ:
Rollbacks ਹਮੇਸ਼ਾ perfect "down migration" ਨਹੀਂ ਹੁੰਦੇ। ਕਈ ਵਾਰੀ ਸਭ ਤੋਂ ਵਧੀਆ rollback backup restore ਹੀ ਹੁੰਦੀ ਹੈ। ਜੇ ਤੁਸੀਂ Koder.ai ਵਰਤ ਰਹੇ ਹੋ, ਤਾਂ ਇਹ ਵੀ ਫੈਸਲਾ ਕਰਨ ਯੋਗ ਹੈ ਕਿ risky changes ਤੋਂ ਪਹਿਲਾਂ snapshots ਤੇ ਕਦੇ ਨਿਰਭਰ ਕਰਨਾ ਹੈ ਤਾਂ ਕਿ ਤੇਜ਼ recovery ਲਈ rollback ਮਿਲ ਸਕੇ।
ਕਲਪਨਾ ਕਰੋ ਇੱਕ ਛੋਟੇ SaaS ਐਪ ਦੀ ਜਿੱਥੇ ਲੋਕ teams ਵਿੱਚ ਜੁੜਦੇ ਹਨ, projects ਬਣਾਉਂਦੇ ਹਨ, ਅਤੇ tasks ਟ੍ਰੈਕ ਕਰਦੇ ਹਨ।
ਦਿਨ ਇੱਕ ਲਈ ਸਿਰਫ਼ ਜਰੂਰੀ fields ਲਿਖਣ ਨਾਲ ਸ਼ੁਰੂ ਕਰੋ:
ਰਿਸ਼ਤੇ ਸਿੱਧੇ ਹਨ: ਇੱਕ team ਕੋਲ ਬਹੁਤ projects ਹਨ, ਇੱਕ project ਕੋਲ ਬਹੁਤ tasks ਹਨ, ਅਤੇ users team_members ਰਾਹੀਂ teams ਵਿੱਚ ਸ਼ਾਮਿਲ ਹੁੰਦੇ ਹਨ। Tasks ਇੱਕ project ਨਾਲ ਸੰਬੰਧਤ ਹੁੰਦੇ ਹਨ ਅਤੇ ਇੱਕ user ਨੂੰ assigned ਹੋ ਸਕਦੇ ਹਨ।
ਹੁਣ ਕੁਝ constraints ਜੋ ਆਮ ਤੌਰ 'ਤੇ ਦੀਰਘ ਸਮੇਂ ਬਾਅਦ bugs ਰੋਕਦੇ ਹਨ ਜੋ ਤੁਸੀਂ ਦੇਖਦੇ ਹੋ:
citext ਵਰਤਦੇ ਹੋ ਤਾਂ case-insensitive)।Indexes ਨੂੰ ਅਸਲ screens ਨਾਲ ਮੇਲ ਕਰਵਾਓ। ਉਦਾਹਰਣ ਵਜੋਂ, ਜੇ task list project ਅਤੇ state ਨਾਲ filter ਕਰਦੀ ਅਤੇ newest ਨਾਲ sort ਕਰਦੀ ਹੈ, ਤਾਂ ਐਸਾ index ਯੋਜਨਾ ਕਰੋ: tasks (project_id, state, created_at DESC). ਜੇ “My tasks” ਇੱਕ ਮੁੱਖ view ਹੈ, ਤਾਂ tasks (assignee_user_id, state, due_date) ਜਿਹਾ index ਮਦਦ ਕਰ ਸਕਦਾ ਹੈ।
ਮਾਈਗ੍ਰੇਸ਼ਨਸ ਲਈ, ਪਹਿਲੀ ਸੈੱਟ ਸੁਰੱਖਿਅਤ ਅਤੇ ਸਧਾਰਨ ਰੱਖੋ: tables ਬਣਾਓ, primary keys, foreign keys, ਅਤੇ core unique constraints। ਇੱਕ ਅੱਗੇ ਵਾਲਾ ਬਦਲਾਅ ਉਹ ਹੋ ਸਕਦਾ ਹੈ ਜੋ ਤੁਸੀਂ ਵਰਤੋਂ ਤੋਂ ਬਾਅਦ ਸ਼ਾਮਿਲ ਕਰੋ, ਜਿਵੇਂ tasks 'ਤੇ soft delete (deleted_at) ਜੋੜਨਾ ਅਤੇ “active tasks” indexes ਨੂੰ ਸੋਧਣਾ ਤਾਂ ਕਿ deleted rows ਨੂੰ ਨਜ਼ਰਅੰਦਾਜ਼ ਕੀਤਾ ਜਾ ਸਕੇ।
ਜ਼ਿਆਦਾਤਰ ਦੁਬਾਰਿਆਂ ਦਾ ਕਾਰਨ ਇਹ ਹੈ ਕਿ ਪਹਿਲਾ schema ਨਿਯਮਾਂ ਅਤੇ ਅਸਲ ਵਰਤੋਂ ਦੇ ਵੇਰਵੇ ਤੋਂ ਖਾਲੀ ਹੁੰਦਾ ਹੈ। ਇੱਕ ਚੰਗੀ ਯੋਜਨਾ ਪਾਸ perfect diagrams ਦੀ ਗੱਲ ਨਹੀਂ ਹੈ। ਇਹ ਜ਼ਿਆਦਾ ਤੌਰ 'ਤੇ ਜਲਦੀ ਜ਼ਖੀਰੇ (traps) ਨੂੰ ਪਛਾਣਣਾ ਹੈ।
ਇੱਕ ਆਮ ਗਲਤੀ ਮਹੱਤਵਪੂਰਨ ਨਿਯਮਾਂ ਨੂੰ ਸਿਰਫ application ਕੋਡ ਵਿੱਚ ਰੱਖਣਾ ਹੈ। ਜੇ ਕੋਈ value unique, present, ਜਾਂ ਇੱਕ range ਵਿੱਚ ਹੋਣੀ ਚਾਹੀਦੀ ਹੈ, ਤਾਂ database ਵਿੱਚ enforce ਕਰੋ। ਨਹੀਂ ਤਾਂ background job, ਨਵਾਂ endpoint, ਜਾਂ manual import ਤੁਹਾਡੀ ਲਾਜ਼ਮੀ logic ਨੂੰ ਬਾਇਪਾਸ ਕਰ ਸਕਦਾ ਹੈ।
ਦੂਜੀ ਆਮ ਗਲਤੀ indexes ਨੂੰ ਬਾਅਦ ਦਾ ਸਮੱਸਿਆ ਸਮਝਣਾ ਹੈ। ਲਾਂਚ ਤੋਂ ਬਾਅਦ indexes ਜੋੜਨਾ ਅਕਸਰ ਅਨੁਮਾਨਾਂ 'ਤੇ ਆਧਾਰਿਤ ਹੁੰਦਾ ਹੈ, ਅਤੇ ਤੁਸੀਂ ਗਲਤ ਚੀਜ਼ index ਕਰ ਸਕਦੇ ਹੋ ਜਦੋਂ ਹਕੀਕਤ ਵਿੱਚ slow query ਇੱਕ join ਜਾਂ status ਫਿਲਟਰ ਉੱਤੇ ਹੁੰਦੀ ਹੈ।
Many-to-many tables ਵੀ ਖਾਮੋਸ਼ ਬੱਗਸ ਦਾ ਸਰੋਤ ਹਨ। ਜੇ join table duplicates ਨੂੰ ਰੋਕਦਾ ਨਹੀਂ, ਤਾਂ ਤੁਸੀਂ ਇੱਕੋ ਰਿਸ਼ਤਾ ਦੋ ਵਾਰੀ ਸਟੋਰ ਕਰ ਸਕਦੇ ਹੋ ਅਤੇ ਫਿਰ ਘੰਟਿਆਂ ਨੂੰ ਡਿਬੱਗ ਕਰਨਾ ਪਵੇਗਾ “ਇਹ user ਦੋ ਵਾਰ ਕਿਉਂ ਦਿਖਦਾ ਹੈ?”
ਇਹ ਵੀ ਆਸਾਨ ਹੈ ਕਿ ਪਹਿਲਾਂ tables ਬਣਾਉਣ ਅਤੇ ਫਿਰ realize ਕਰਨ ਕਿ ਤੁਹਾਨੂੰ audit logs, soft deletes, ਜਾਂ event history ਦੀ ਲੋੜ ਹੈ। ਇਹ additions endpoints ਅਤੇ reports ਵਿੱਚ ਰਿਪਲ ਹੋ ਜਾਂਦੇ ਹਨ।
ਅਖ਼ਿਰ ਨੂੰ, JSON columns ਲਚਕੀਲੇ ਲਈ ਆਕਰਸ਼ਕ ਹੁੰਦੇ ਹਨ, ਪਰ ਉਹ checks ਨੂੰ ਹਟਾ ਦਿੰਦੇ ਹਨ ਅਤੇ indexing ਨੂੰ ਮুশਕਲ ਬਣਾਉਂਦੇ ਹਨ। JSON ਉਹਨਾਂ ਲਈ ਠੀਕ ਹੈ ਜੋ ਬਹੁਤ ਹੀ ਬਦਲਨ ਵਾਲੇ payloads ਹਨ, ਨਾ ਕਿ core business fields ਲਈ।
ਕੋਡ ਜਨਰੇਟ ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ ਇਹ quick fix list ਚਲਾਓ:
user_id + role_id).ਇੱਥੇ ਰੁਕੋ ਅਤੇ ਯਕੀਨ ਕਰੋ ਕਿ ਯੋਜਨਾ ਪਰਯਾਪਤ ਹੈ ਤਾਂ ਜੋ ਤੁਸੀਂ ਬਿਨਾਂ ਘੁੰਮਣ-ਫਿਰਣ ਦੇ ਕੋਡ ਜਨਰੇਟ ਕਰ ਸਕੋ। ਮਕਸਦ perfection ਨਹੀਂ; ਇਹ ਉਹ gaps ਫਸਾਉਣ ਹੈ ਜੋ ਬਾਅਦ ਵਿੱਚ ਦੁਬਾਰਿਆਂ ਦਾ ਕਾਰਣ ਬਣਦੇ ਹਨ: ਗੁੰਝਲਦਾਰ ਰਿਸ਼ਤੇ, ਅਸਪਸ਼ਟ ਨਿਯਮ, ਅਤੇ indexes ਜੋ ਅਸਲ ਵਰਤੋਂ ਨਾਲ मेल ਨਹੀਂ ਖਾਂਦੇ।
ਇਸਨੂੰ ਇੱਕ ਤੇਜ਼ pre-flight ਜਾਂਚ ਵਜੋਂ ਵਰਤੋ:
amount >= 0 ਜਾਂ allowed statuses)।ਇੱਕ ਛੋਟਾ sanity ਟੈਸਟ: ਸੋਚੋ ਇੱਕ teammate ਕੱਲ੍ਹ ਆ ਰਿਹਾ ਹੈ। ਕੀ ਉਹ ਪਹਿਲੇ endpoints ਬਿਲਡ ਕਰ ਸਕੇਗਾ ਬਿਨਾਂ ਹਰ ਘੰਟੇ "ਇਹ null ਹੋ ਸਕਦਾ ਹੈ?" ਜਾਂ "delete ਤੇ ਕੀ ਹੁੰਦਾ ਹੈ?" ਪੁੱਛਦੇ ਰਹਿਣ ਤੋਂ?
ਜਦ ਤੁਸੀਂ ਯੋਜਨਾ ਨੂੰ ਸਪਸ਼ਟ ਪੜ੍ਹ ਸਕਦੇ ਹੋ ਅਤੇ ਮੁੱਖ flows ਕਰਨ ਨੂੰ ਕਾਗਜ਼ ਉੱਤੇ ਸਹੀ ਲੱਗਦੇ ਹਨ, ਇਸਨੂੰ ਕਾਰਜਯੋਗ ਬਣਾਓ: ਇੱਕ ਅਸਲੀ schema ਅਤੇ migrations ਲਿਖੋ।
ਪਹਿਲੀ migration ਨਾਲ ਸ਼ੁਰੂ ਕਰੋ ਜੋ tables, types (ਜੇ ਤੁਸੀਂ enums ਵਰਤਦੇ ਹੋ), ਅਤੇ ਜ਼ਰੂਰੀ constraints ਬਣਾਉਂਦੀ ਹੈ। ਪਹਿਲੀ ਕੋਸ਼ਿਸ਼ ਛੋਟੀ ਪਰ ਸਹੀ ਰੱਖੋ। ਥੋੜ੍ਹਾ seed data ਲੋਡ ਕਰੋ ਅਤੇ ਉਹ ਕੁਈਰੀਆਂ ਚਲਾਓ ਜੋ ਤੁਹਾਡੀ ਐਪ ਨੂੰ ਲੋੜੀਂਦੀਆਂ ਹੋਣ। ਜੇ ਕੋਈ flow awkward ਮਹਿਸੂਸ ਹੋਵੇ, ਤਾਂ migration history ਛੋਟੀ ਹੋਣ 'ਤੇ schema ਠੀਕ ਕਰੋ।
ਉਨ੍ਹਾਂ ਨੂੰ ਮਾਡਲ ਅਤੇ endpoints ਤਦ ਹੀ ਜਨਰੇਟ ਕਰੋ ਜਦੋਂ ਤੁਸੀਂ ਕਈ end-to-end actions ਟੈਸਟ ਕਰ ਸਕਦੇ ਹੋ schema ਦੇ ਨਾਲ (create, update, list, delete, ਅਤੇ ਇੱਕ ਅਸਲ ਬਿਜ਼ਨਸ action)। ਕੋਡ ਜਨਰੇਸ਼ਨ ਸਭ ਤੋਂ ਤੇਜ਼ ਹੁੰਦਾ ਹੈ ਜਦੋਂ tables, keys, ਅਤੇ naming ਇਤਨੇ ਸਥਿਰ ਹੋਣ ਕਿ ਤੁਸੀਂ ਅਗਲੇ ਦਿਨ ਸਭ ਕੁਝ rename ਨਾ ਕਰਨਾ ਪਏ।
ਇੱਕ ਪ੍ਰਯੋਗਿਕ loop ਜੋ ਦੁਬਾਰਿਆਂ ਨੂੰ ਘੱਟ ਰੱਖਦਾ ਹੈ:
ਅੱਗੇ ਤੋਂ ਪਹਿਲਾਂ ਫੈਸਲਾ ਕਰੋ ਕਿ ਤੁਸੀਂ ਕੀ ਬੇਨਤੀ database ਵਿੱਚ validate ਕਰਨਾ ਹੈ ਅਤੇ ਕੀ API layer ਵਿੱਚ। database ਵਿੱਚ permanent rules ਰੱਖੋ (foreign keys, unique constraints, check constraints)। soft rules API ਵਿੱਚ ਰੱਖੋ (feature flags, temporary limits, ਅਤੇ complex cross-table logic ਜੋ ਅਕਸਰ ਬਦਲਦਾ ਹੈ)।
ਜੇ ਤੁਸੀਂ Koder.ai ਵਰਤਦੇ ਹੋ, ਤਾਂ ਇੱਕ ਸਮਝਦਾਰ ਤਰੀਕਾ ਇਹ ਹੈ ਕਿ ਪਹਿਲਾਂ Planning Mode ਵਿੱਚ entities ਅਤੇ migrations ਉੱਤੇ ਸਹਿਮਤ ਹੋ ਜਾਵੋ, ਫਿਰ ਤੁਹਾਡਾ Go + PostgreSQL backend ਜਨਰੇਟ ਕਰੋ। ਜੇ ਕੋਈ ਬਦਲਾਅ ਗਲਤ ਜਾਇਆ, ਤਾਂ snapshots ਅਤੇ rollback ਤੁਹਾਨੂੰ ਇੱਕ ਜਾਣੇ-ਮਾਣੇ ਵਰਜਨ ਤੇ ਤੇਜ਼ੀ ਨਾਲ ਵਾਪਸ ਲਿਆਉਣ ਵਿੱਚ ਮਦਦ ਕਰ ਸਕਦੇ ਹਨ।
Plan the schema first. It sets a stable data contract (tables, keys, constraints) so generated models and endpoints don’t need constant renames and rewrites later.
In practice: write your entities, relationships, and top queries, then lock in constraints, indexes, and migrations before you generate code.
Write 2–3 sentences describing what the app must remember and what users must be able to do.
Then list:
This gives you enough clarity to design tables without overbuilding.
Start by listing the nouns you keep repeating (user, project, invoice, task). For each one, add one sentence: what it is and why it exists.
If you can’t describe it clearly, you’ll likely end up with vague tables like items or misc and regret it later.
Default to a single consistent ID strategy across your schema.
UUIDs: great when records can be created from many places (web/mobile/jobs) or you don’t want predictable IDsbigint: smaller, a bit faster, and simpler when everything is server-createdIf you need a human-friendly identifier, add a separate unique column (like project_code) instead of using it as the primary key.
Decide it per relationship based on what users expect and what must be preserved.
Common defaults:
RESTRICT/NO ACTION when deleting a parent would erase important records (like customers → orders)CASCADE when child rows have no meaning without the parent (like order → line items)Make this decision early because it affects API behavior and edge cases.
Put permanent rules in the database so every writer (API, scripts, imports, admin tools) is forced to behave.
Prioritize:
Start from real query patterns, not guesses.
Write 5–10 plain-English queries (filters + sort), then index for those:
status, user_id, created_atCreate a join table with two foreign keys and a composite unique constraint.
Example pattern:
team_members(team_id, user_id, role, joined_at)UNIQUE (team_id, user_id) to prevent duplicatesThis prevents subtle bugs like “why does this user appear twice?” and keeps your queries clean.
Default to:
timestamptz for timestamps (fewer time zone surprises)numeric(12,2) or integer cents for money (avoid floats)CHECK constraintsKeep types consistent across tables (same type for the same concept) so joins and validations stay predictable.
Use small, reviewable migrations and avoid breaking changes in one step.
A safe path:
Also decide upfront how you’ll handle seed/reference data so every environment matches.
PRIMARY KEY on every tableFOREIGN KEY for every “belongs to” columnUNIQUE where duplicates cause real harm (email, (team_id, user_id) in join tables)CHECK for simple rules (non-negative amounts, allowed statuses)NOT NULL for fields required for the row to make sense(account_id, created_at)Avoid indexing everything; each index slows inserts and updates.