1. Choose the required management boundary
Migration starts with application dependencies rather than a preferred service name. Azure SQL Database, SQL Managed Instance and SQL Server on a VM share technology but offer different management boundaries. A confirmed requirement to install software on the SQL host operating system points toward an option providing that control and its associated operational responsibility. An application using instance-level features can justify evaluating Managed Instance without assuming absolute compatibility before testing. Record jobs, authentication, cross-database connections, drivers and integrations. In the fictional project, the supplier lists a host agent as mandatory but cannot explain its purpose. The architect requests evidence and supported alternatives before accepting the ongoing cost of operating VMs. The resulting decision should connect each retained dependency to a validated requirement.
2. Size elastic pools using simultaneous demand
Elastic pools let databases share resources within a defined budget. Their benefit depends on how demand peaks overlap. Adding daily averages can hide a closing interval when all databases need capacity together; adding historical individual maxima can overstate needs when those peaks never coincide. Observe representative windows and retain headroom for variability and operational work. Set per-database limits where appropriate and measure the effect of demanding consumers. The local model adds three fictional series at each instant and includes reserve. It predicts neither Azure vCores, DTUs, latency nor price. Its purpose is to show why the maximum of time-aligned sums differs from the sum of individual maxima. The team must then test the real service with appropriate metrics and workloads.
3. Do not confuse database and instance pooling
A SQL Database elastic pool and a Managed Instance instance pool group different units. The first organizes databases; the second hosts multiple instances with allocated resources on shared infrastructure. If each application needs instance-level configuration, that distinction belongs in compatibility and isolation analysis. Do not assume that moving databases into a pool gives them every SQL Server instance feature. Do not assume all sharing means a dedicated VM per workload either. In the fictional case, three small applications have separate instance requirements and moderate peaks. Compare allocated resources, required isolation, maintenance windows and growth capacity instead of choosing only the option with the fewest portal resources. Record which administrative boundary each application owner expects to retain after migration.
4. Model serverless idle time and resumption
Serverless adjusts compute within configured limits, but savings and user experience depend on usage patterns. A database with long idle intervals can benefit if the first request tolerates resumption and the application handles transient errors. Sessions kept open by monitoring or incompatible features can prevent pausing; check current requirements instead of assuming no business requests means no activity. Consulted documentation distinguishes available General Purpose pausing from Hyperscale pausing in preview. Do not transfer guarantees across tiers without checking support and status. During a proof of concept, measure idle duration, pause events, resumption, minimum utilization and first-request behavior. Cost must include storage and compute while the database remains active even under light demand. Use those observations to choose an operating model rather than promising savings from the label alone.
5. Separate lag-tolerant reports from write confirmation
Read scale-out can relieve the writable replica by serving queries on a read replica. The decision requires identifying which flows tolerate lag. A periodic report can accept changes not yet visible, whereas immediate confirmation of a user’s own update can have a different contract. ApplicationIntent=ReadOnly is connection intent, not permission to write to a replica or a global freshness guarantee. In Hyperscale, named replicas allow independent compute objectives and access for read workloads; they should not be confused with a separate-region copy for regional disaster recovery. Before handover, record endpoints, connection strings, permissions and freshness tests per flow. A test that merely executes SELECT successfully does not demonstrate that reading meets the business’s timing expectation.
6. Treat restoration as a new data delivery
Restoring a database from backup should not be confused with undoing only the last erroneous instruction in the serving database. In the SQL Database recovery path, restore creates a database requiring validation and integration into the recovery plan. The team identifies the correct point, destination, required configuration and legitimate later changes needing reconciliation. An application can still point to the old endpoint while the restored database exists without consumers. The PM should track validation, cutover decision, access, dependencies and the temporary cost of both copies. In the exercise, the business owner confirms positions and totals before the team declares success. A completed restore job is partial technical evidence rather than automatic incident closure. Preserve enough information to explain both the chosen recovery point and any reconciled later work.
def required_capacity(series, reserve):
if reserve < 0 or not series or not series[0]:
raise ValueError("invalid fictional capacity input")
if any(len(row)!= len(series[0]) or any(v < 0 for v in row) for row in series):
raise ValueError("unaligned or negative demand")
totals = [sum(values) for values in zip(*series)]
return max(totals) + reserve
loads = [[20, 70, 30], [60, 20, 50], [10, 5, 10]]
assert required_capacity(loads, 10) == 105
assert sum(max(row) for row in loads) + 10 == 150
assert required_capacity([[70], [60], [10]], 10) == 150
assert required_capacity([[0, 0], [0, 0]], 10) == 10
assert required_capacity(loads, 0) == 95
print("five fictional capacity checks passed; no Azure sizing or pricing prediction")
Fictional case: three databases peak at different times. The model calculates simultaneous demand and reserve, but the project accepts the pool only after also rehearsing a closing interval where two peaks coincide.
Common pitfalls
Choosing by product name; ignoring simultaneous peaks; confusing instance and elastic pools; promising pausing in every configuration; validating reads without measuring freshness.
Related topics: FinOps and sizing · RPO and data validation · Migration and dependencies
SQL selection should combine compatibility, demand, initial response, freshness and ability to recover business-accepted data.
Reference: Azure SQL deployment options · AZ-305 objectives 2026-04-17