Ένα API σπάνια μένει ακριβώς όπως σχεδιάστηκε την πρώτη ημέρα. Προστίθενται πεδία, αλλάζουν επιχειρηματικοί κανόνες και εμφανίζονται νέοι clients: mobile app, ERP, partner portal ή τρίτη εταιρεία. Η εύκολη αλλαγή στο backend μπορεί να σπάσει έναν client που δεν αναπτύσσεται και δεν γίνεται deploy ταυτόχρονα.
Το API versioning δεν είναι απλώς το /v1 μέσα σε ένα URL. Είναι πολιτική συμβατότητας, τρόπος κυκλοφορίας αλλαγών και συμφωνία για το πόσο χρόνο υποστηρίζεται κάθε contract.
Πρώτα ξεχωρίστε compatible από breaking αλλαγές
Πολλές επεκτάσεις μπορούν να γίνουν χωρίς νέα major version. Συνήθως backward compatible θεωρούνται:
- προσθήκη νέου optional πεδίου σε response
- νέο endpoint ή νέα προαιρετική παράμετρος
- νέο event type που οι consumers έχουν σχεδιαστεί να αγνοούν
- βελτίωση performance χωρίς αλλαγή αποτελέσματος
Breaking αλλαγές είναι συχνά:
- μετονομασία ή αφαίρεση πεδίου
- αλλαγή τύπου από string σε number
- μετατροπή optional πεδίου σε required
- διαφορετική σημασία για υπάρχουσα τιμή
- αλλαγή pagination, authentication ή error format
- αφαίρεση enum value ή προσθήκη value όταν ο client θεωρεί ότι γνωρίζει όλες τις επιλογές
Η Google Cloud τεκμηρίωση διαχωρίζει τις backward-compatible αλλαγές από εκείνες που σπάνε client code και προτείνει νέα major version για τις δεύτερες, με παράλληλη λειτουργία των εκδόσεων ώστε οι clients να επιλέξουν πότε θα μετακινηθούν.
Το /v1 δεν λύνει μόνο του το πρόβλημα
Η έκδοση μπορεί να δηλώνεται στο path, σε header ή με άλλο μηχανισμό. Η επιλογή έχει trade-offs, αλλά η συνέπεια είναι σημαντικότερη από μια θεωρητική «τέλεια» μορφή. Το path είναι ορατό σε logs, documentation και routing:
GET /api/v1/customers/1842
GET /api/v2/customers/1842
Ακόμη και με versioned URL, η βάση δεδομένων και οι επιχειρηματικές οντότητες συνήθως είναι κοινές. Αν το v2 αλλάζει ένα record, το v1 πρέπει να συνεχίσει να το διαβάζει και να το ενημερώνει με ασφαλή τρόπο. Η διατήρηση δύο εντελώς ανεξάρτητων implementations χωρίς κοινό domain model αυξάνει το κόστος και δημιουργεί αποκλίσεις.
Σχεδιάστε clients που αντέχουν σε επέκταση
Ένας client δεν πρέπει να αποτυγχάνει επειδή εμφανίστηκε επιπλέον πεδίο στο JSON. Πρέπει να αγνοεί ιδιότητες που δεν γνωρίζει και να μην βασίζεται στη σειρά τους. Στα enums χρειάζεται UNKNOWN ή UNSPECIFIED fallback, γιατί στο μέλλον μπορεί να προστεθεί νέα τιμή.
Στα update endpoints, το PATCH με ρητά πεδία συχνά είναι ασφαλέστερο από ένα πλήρες PUT που στέλνει πίσω παλιό representation και μπορεί να σβήσει νέα πεδία. Χρειάζεται επίσης διάκριση μεταξύ «δεν στάλθηκε», null και κενής τιμής.
Contract και schema ως πηγή αλήθειας
Το OpenAPI schema δεν πρέπει να είναι χειροποίητο έγγραφο που μένει πίσω από τον κώδικα. Μπορεί να χρησιμοποιείται για validation, generated clients, documentation και contract tests. Κάθε αλλαγή ελέγχεται αυτόματα για πιθανό breaking impact.
Χρήσιμο pipeline περιλαμβάνει:
- lint και schema validation
- σύγκριση με την τρέχουσα production έκδοση
- contract tests με αντιπροσωπευτικούς consumers
- integration tests για authentication και errors
- deployment σε staging με πραγματικές εκδόσεις clients
Το schema εξηγεί τη μορφή, αλλά όχι πάντα τη σημασία. Για αυτό χρειάζονται παραδείγματα, changelog και σαφής περιγραφή των invariants.
Deprecation χωρίς αιφνιδιασμό
Μια έκδοση δεν πρέπει να εξαφανίζεται επειδή κυκλοφόρησε η επόμενη. Ορίζεται lifecycle: active, deprecated και sunset. Οι καταναλωτές ενημερώνονται με ημερομηνίες, migration guide και συγκεκριμένες διαφορές.
Πριν απενεργοποιηθεί το v1, χρειάζεται να ξέρουμε ποιος το χρησιμοποιεί. Τα API keys ή client identifiers, τα access logs και τα metrics ανά version δείχνουν ενεργούς consumers. Τα προσωπικά δεδομένα δεν πρέπει να καταγράφονται άσκοπα, αλλά η έκδοση, το endpoint, το status code και το client ID είναι κρίσιμα operational στοιχεία.
Ένα migration guide πρέπει να περιέχει old και new request/response, mapping πεδίων, νέα error cases και βήματα rollout. Το «διαβάστε το νέο documentation» δεν είναι επαρκής οδηγία.
Παράλληλη λειτουργία και adapters
Όταν v1 και v2 λειτουργούν μαζί, είναι χρήσιμο να μεταφράζονται σε κοινές domain commands. Το version-specific layer κάνει parsing και formatting, ενώ ο πυρήνας εφαρμόζει τους ίδιους επιχειρηματικούς κανόνες.
v1 request -> v1 adapter -> domain service -> v1 response
v2 request -> v2 adapter -> domain service -> v2 response
Έτσι μια διόρθωση σε pricing ή authorization εφαρμόζεται και στις δύο εκδόσεις. Οι adapters δεν πρέπει να κρύβουν ασύμβατες έννοιες με παραπλανητικό τρόπο. Αν το domain έχει αλλάξει ριζικά, μπορεί να χρειαστεί πραγματική migration στρατηγική και όχι απλή μετατροπή JSON.
Webhooks και events χρειάζονται επίσης versioning
Τα integrations συχνά σπάνε όχι από REST endpoints αλλά από webhook payloads. Κάθε event πρέπει να έχει schema version, σταθερό event ID και τεκμηριωμένη πολιτική για νέα fields. Ο consumer πρέπει να αποθηκεύει και να επεξεργάζεται idempotently το event.
Σε μεγάλη αλλαγή μπορούν να λειτουργούν δύο webhook versions ή ο consumer να επιλέγει version κατά την εγγραφή του endpoint. Δεν είναι ασφαλές να αλλάζει σιωπηλά το payload για όλους την ίδια ημέρα.
Rollout και rollback
Η νέα έκδοση κυκλοφορεί σταδιακά. Internal clients μετακινούνται πρώτοι, ακολουθούν selected partners και μετά το υπόλοιπο κοινό. Παρακολουθούνται error rate, latency, validation failures και διαφορές αποτελεσμάτων.
Το rollback δεν σημαίνει απαραίτητα διαγραφή του v2. Μπορεί να σταματήσει η δρομολόγηση νέων clients, ενώ διατηρείται η λειτουργία για όσους έχουν ήδη μεταφερθεί. Οι database migrations πρέπει να είναι συμβατές με το διάστημα όπου τρέχουν και οι δύο εκδόσεις.
Πώς το υλοποιεί η Ai Foundry
Στην Ai Foundry σχεδιάζουμε APIs ως contracts μεταξύ ανεξάρτητων συστημάτων. Καταγράφουμε consumers, ορίζουμε κανόνες συμβατότητας και χρησιμοποιούμε OpenAPI schemas, validation και contract tests για να εντοπίζουμε breaking changes πριν φτάσουν στο production.
Όταν χρειάζεται νέα major version, κρατάμε version-specific adapters γύρω από κοινό domain layer, προσθέτουμε metrics ανά client και οργανώνουμε deprecation με migration guide. Στις συνδέσεις e-shop, ERP, CRM και mobile apps ελέγχουμε και webhooks, retries και idempotency. Έτσι η εξέλιξη της εφαρμογής δεν εξαρτάται από ένα επικίνδυνο simultaneous deploy όλων των συστημάτων.
Συμπέρασμα
Το καλό API versioning επιτρέπει στην υπηρεσία να εξελίσσεται χωρίς να μεταφέρει το ρίσκο στους clients. Backward-compatible σχεδίαση, σαφή contracts, παράλληλη υποστήριξη και μετρήσιμη απόσυρση κάνουν τις integrations προβλέψιμες και μειώνουν τις διακοπές.