Cloud Tech by Victor

Search

30 results for “databases

Search results

Databases

PostgreSQL Fundamentals

How tables, joins, aggregates, window functions, and transactions fit together in everyday PostgreSQL work, from the actual internals of a single index (covered in PostgreSQL Indexes) to the SQL you write day to day.

PostgreSQL Fundamentals

What is the difference between `INNER JOIN` and `LEFT JOIN`?

`INNER JOIN` returns only rows where the join condition matches in both tables, a row from either side with no match is dropped entirely from the result. `LEFT JOIN` returns every row from the left table regardless of whether a match exists on the right, filling in `NULL` for the right table's columns when there isn't one. Reaching for `INNER JOIN` when you actually need "every user, even ones with zero orders" silently drops exactly the rows you wanted to see, which is why an unexpectedly short result set is one of the most common join bugs.

PostgreSQL Fundamentals

What is the difference between GROUP BY aggregation and a window function like `ROW_NUMBER() OVER (...)`?

`GROUP BY` collapses every row in a group into a single output row per group, you lose access to the individual rows once you've aggregated. A window function computes its result (a rank, a running total, a row number) per row while keeping every individual row in the output, `PARTITION BY` defines the grouping for that calculation, but nothing is collapsed. This is why "give me each order plus that customer's running total" needs a window function, while "give me one row per customer with their total" is a plain `GROUP BY`.

PostgreSQL Fundamentals

Why does wrapping several statements in `BEGIN`/`COMMIT` matter, even for a multi-step operation that's logically one action?

Without an explicit transaction, PostgreSQL commits each statement independently the moment it succeeds; if a multi-step operation (debit one account, credit another) fails halfway through, the database is left in an inconsistent, partially-applied state with no way to undo the completed step. Wrapping the statements in `BEGIN`/`COMMIT` groups them so they can be committed or rolled back together, but that alone isn't automatic protection against every failure mode: PostgreSQL only aborts a transaction on its own when a statement raises an actual SQL error, an `UPDATE` that runs successfully but matches zero rows (a mistyped account id, for instance) is not an error at all, and would otherwise be committed as if the transfer had actually happened. Making the transaction genuinely safe means checking that each `UPDATE` affected exactly the one row expected and issuing an explicit `ROLLBACK` if either check fails, only issuing `COMMIT` once both checks pass.

Databases

PostgreSQL vs MySQL

How PostgreSQL and MySQL actually differ in data types, concurrency, indexing, and replication, and which one fits which workload.

Databases

Redis vs Memcached

How Redis and Memcached differ in data structures, persistence, clustering, and threading, and which cache fits which workload.

Databases

Database Locking & Deadlocks

How PostgreSQL's row-level lock modes actually differ in strength, why it can't predict which transaction a deadlock will abort, and why acquiring locks in a consistent order is the real fix, not a "nice to have".

System Design

Database Sharding

Why a monotonically increasing shard key like a sequential ID or timestamp routes every new write to the same shard, and why hashed sharding fixes that distribution problem at the cost of range queries no longer targeting a single shard.

Databases

Database Transactions & Isolation Levels

Why PostgreSQL's default Read Committed isolation still allows non-repeatable reads and phantom reads, and why Repeatable Read and Serializable trade that risk for transactions your application has to be ready to retry.

Database Sharding

Why does using a monotonically increasing field (a sequential ID, a timestamp) as a shard key concentrate all new writes onto one shard, even with range-based sharding across many shards?

With range-based sharding, chunks are assigned contiguous ranges of shard-key values, and a monotonically increasing key means every new document's value is higher than every previously inserted one, so all new inserts land in whatever chunk currently owns the highest range, which lives on one specific shard. Every other shard, holding older, lower-valued ranges, receives none of the new write traffic at all, the exact "hot shard" problem, all insert load concentrated on a single shard regardless of how many total shards the cluster has.

Retrieval-Augmented Generation (RAG)

Why does a chunk like "The company's revenue grew by 3% over the previous quarter" cause a retrieval failure even if it's embedded correctly?

That sentence is only meaningful with context the isolated chunk doesn't carry, which company, which quarter, information that likely lived in a heading or preceding paragraph that didn't survive the chunking boundary. Embedded on its own, the chunk's vector represents a generic, context-free statement about revenue growth, which means it won't be retrieved reliably for a query about "ACME Corp Q2 2023 earnings" even though it's exactly the right chunk, because nothing in its embedding actually encodes that it's about ACME Corp or Q2 2023 at all.

Blog

Deploying a Scalable Azure Environment with Bicep: VMs, NSGs, Subnets & Load Balancer (Step-by-Step Lab)

A hands-on IaC walkthrough using VS Code and Bicep to build a secure, highly available Azure environment.

Cloud Cost Optimization

What is the difference between a reserved/committed-use discount and a spot/preemptible instance, and when does each make sense?

A committed-use discount (reserved instances, savings plans) trades a usage commitment, a fixed amount of spend or capacity over a term, typically one or three years, for a significant price reduction on workloads you know will run continuously. Spot/preemptible instances offer a much steeper discount in exchange for the provider being able to reclaim the capacity with little notice, making them suitable only for interruption-tolerant workloads (batch jobs, stateless workers, CI runners) rather than anything requiring guaranteed uptime. Committed-use addresses predictable steady-state load; spot addresses flexible, interruption-tolerant load, using either for the wrong workload type either wastes the discount or causes outages.

LLM Evaluation & Reducing Hallucinations

Why does explicitly telling a model it's allowed to say "I don't know" measurably reduce hallucination, and what's a second, complementary technique for the same problem?

Without that explicit permission, a model under an implicit expectation to always produce a confident, complete answer will sometimes fill a real information gap with a plausible-sounding but fabricated one; stating outright that uncertainty is an acceptable answer removes that pressure and lets the model surface "I don't have enough information" instead of guessing. A complementary technique for long documents is asking the model to first extract direct, word-for-word quotes relevant to the task before generating any analysis, grounding its response in verifiable text it actually has in front of it, and then citing which quote supports each claim, rather than generating an answer freely and hoping it stayed faithful to the source.

Retrieval-Augmented Generation (RAG)

What problem does RAG solve that simply pasting an entire knowledge base into the prompt doesn't?

A real knowledge base, product docs, legal filings, support history, routinely exceeds any model's context window, and even when it technically fits, stuffing everything into every request wastes tokens on mostly-irrelevant content and degrades accuracy as context grows. RAG instead retrieves only the specific chunks relevant to the current query at request time, from a knowledge base that's been pre-processed into searchable chunks and embeddings, so the model gets focused, relevant background knowledge sized to the question actually being asked, not the entire corpus every time.

Consistent Hashing

Why does a real ring hash implementation give each host many positions on the ring instead of just one, and what problem would a single position per host cause?

A host thrown onto the ring at just one point can end up, purely by chance, owning a disproportionately large or small arc of the ring if the hash values happen to land unevenly, since with few points there's no averaging effect smoothing out the randomness. Assigning each host many positions on the ring, scaled by that host's intended weight, so a double-weight host gets roughly twice as many ring entries as a single-weight one, averages out that randomness across many smaller arcs per host, producing a much more even overall traffic distribution than a single coin-flip-like placement per host would.

Database Transactions & Isolation Levels

What's the practical difference between Repeatable Read and Serializable, given that PostgreSQL's Repeatable Read already prevents phantom reads?

PostgreSQL's Repeatable Read goes beyond the SQL standard's minimum and already prevents phantom reads via snapshot isolation, but it can still allow a specific class of anomaly called a serialization anomaly, where the combined effect of several concurrently-committed transactions is not equivalent to any possible serial (one-at-a-time) ordering of them, even though each transaction individually looks consistent. Serializable adds predicate locking on top of snapshot isolation specifically to detect and prevent that remaining anomaly, guaranteeing that the outcome is always equivalent to transactions having run one at a time in some order. The cost is the same as Repeatable Read's, more serialization failures the application must retry, in exchange for the strongest correctness guarantee available.

Embeddings & Vector Search

When does semantic search (via embeddings) actually outperform traditional keyword search, and when might keyword search still win?

Semantic search wins when a query and the relevant document use different words for the same idea, "car won't start" matching a document about "vehicle fails to ignite", since embeddings compare meaning rather than literal tokens, which keyword search cannot do at all. Keyword search still wins, or at least remains necessary, for exact-match needs, an error code, a product SKU, a specific proper noun, where the literal string matters and a semantically "close" but textually different result is actually the wrong answer. This is why production search systems commonly combine both (hybrid search) rather than treating embeddings as a strict replacement for keyword matching.

Hash Tables & the Hash/Equality Contract

Why does Python's documentation say a class defining mutable objects with a custom __eq__ should not implement __hash__ at all?

If an object's hash is derived from fields that can change after the object is already stored as a dict key, mutating it changes its hash value, but the object stays in whatever bucket it was originally placed in based on the old hash, so a subsequent lookup computes the new hash, looks in the new (wrong) bucket, and fails to find an object that is, in fact, still in the dictionary. Making a mutable object unhashable by default (which not defining `__hash__` effectively signals) prevents this specific class of bug entirely, at the cost of not being able to use that object as a dict key or set member at all, a deliberate, documented trade-off favoring correctness over convenience.

Database Locking & Deadlocks

Two transactions each update two of the same two accounts, but in opposite order, and deadlock. What's the actual fix, not just for this pair of transactions, but for the application generally?

The deadlock happens because Transaction 1 locks account A then waits for account B, while Transaction 2 locks account B then waits for account A, a circular wait. The general fix isn't retry logic alone, retries only paper over deadlocks that keep recurring, it's acquiring locks on multiple objects in the same, consistent order everywhere in the application (for example, always locking accounts in ascending id order), which makes the circular-wait pattern structurally impossible rather than merely less frequent. Retry logic is still worth having as a safety net, but consistent lock ordering is what actually eliminates this class of deadlock.

AWS Storage

What is the difference between durability and availability in S3, and why does it matter when picking a storage class?

Durability is the probability that a stored object is not lost over a year, and S3 Standard, Standard-IA, and every Glacier class are all designed for the same 99.999999999% (11 nines) durability. Availability is how often the object can actually be successfully retrieved on demand, and that number does vary by class, 99.99% for Standard down to 99.5% for One Zone-IA. It matters because a cheaper class is not automatically a less durable one, S3 One Zone-IA is exactly as durable as Standard-IA per object, but it is not resilient to the loss of its single Availability Zone at all, since it isn't replicated across multiple zones the way every multi-AZ class is.

Hash Tables & the Hash/Equality Contract

A custom class defines __eq__ based on a value field but leaves __hash__ using default identity-based hashing. What actually goes wrong when you use an instance as a dict key?

In Python 3, simply defining `__eq__` without touching `__hash__` doesn't leave the old identity-based hash in place, Python automatically sets `__hash__` to `None` on that class, making instances unhashable, so using one as a dict key raises `TypeError` immediately rather than corrupting anything. This happens even if a parent class defines `__hash__`: overriding `__eq__` in a subclass sets that subclass's `__hash__` to `None` regardless of what the parent provides, ordinary inheritance does not carry the parent's hash forward. The silent, no-exception version of this bug only happens if the class explicitly keeps or re-supplies an identity-based `__hash__` alongside the value-based `__eq__` (e.g. `__hash__ = object.__hash__`, or, to retain a parent's hash on purpose, `__hash__ = Parent.__hash__`). In that case, two instances with the same value compare equal (`a == b` is `True`) but hash differently, and inserting under key `a` then looking up with an equal-but-distinct key `b` lands in the wrong hash bucket and returns nothing, because the hash mismatch never gave the lookup a chance to even check equality against the right entry.

Sorting Algorithms & Stability

What does it mean for a sorting algorithm to be "stable," and why does that matter for sorting by multiple keys in separate passes?

A stable sort guarantees that when two elements compare as equal under the current sort key, their original relative order is preserved rather than left unspecified. This matters directly for multi-key sorting done as a series of single-key sorts: sort by a secondary key first, then stably sort by the primary key, and elements sharing the same primary key retain their secondary-key order from the first pass, correctly producing a combined sort by (primary, secondary) without needing a single comparator that handles both keys at once. An unstable sort would silently scramble that secondary ordering among equal-primary-key elements.

Secure CI/CD Pipelines

What is the difference between SAST, SCA, and DAST, and where does each run in a pipeline?

SAST (static application security testing) analyzes an application's own source code without running it, catching issues like injection-prone patterns early in the build stage, before an artifact even exists. SCA (software composition analysis) scans a project's third-party dependencies against known-vulnerability databases, since most of a modern application's code is dependencies, not code the team wrote itself. DAST (dynamic application security testing) tests a running instance of the application from the outside, the way an attacker would, and so it runs later, typically against a deployed staging environment, after the artifact exists and is running somewhere.

SQL Injection Prevention

Why does string escaping alone not fully prevent SQL injection?

Escaping tries to neutralize special characters (like quotes) so user input cannot break out of its intended string literal, but it is easy to get wrong, different databases and contexts (string literals, numeric contexts, identifiers, LIKE patterns) have different escaping rules, and a single missed case reopens the vulnerability. Parameterized queries avoid the problem entirely: user input is sent to the database separately from the query structure, so it can never be interpreted as SQL syntax regardless of its content.

Recursion & the Call Stack

Python's own documentation warns that raising the recursion limit "should be done with care, because a too-high limit can lead to a crash." Why doesn't raising the limit simply allow deeper, safe recursion?

The recursion limit is a proxy for the real constraint, actual available C stack space, which is platform-dependent and finite regardless of what the configured limit says. Setting the limit higher than the platform's actual available stack can support doesn't create more stack space, it just removes the early warning that would have raised a clean `RecursionError`, so recursion can now run deep enough to exhaust the real stack and crash the process with a low-level segmentation fault instead, a worse failure mode than the exception the limit was preventing in the first place.

Python Virtual Environments & Packaging

Why does installing packages globally (outside a virtual environment) cause problems across multiple projects?

A global Python installation has exactly one set of installed package versions shared by everything that uses it. Two projects needing different, incompatible versions of the same package (one needs `requests==2.28`, another needs `requests==2.31` for a bug fix it depends on) cannot both be satisfied globally, installing one breaks the other. A virtual environment gives each project its own isolated package set, so version requirements never conflict across projects, and a project's dependencies are fully reproducible independent of whatever else happens to be installed globally.

Rate Limiting Algorithms

A client sends a sudden spike of requests that exceeds the configured rate, but the API doesn't immediately reject any of them. Why not, and when does rejection actually start?

The token bucket has accumulated capacity up to the burst limit, if the client had been under the rate limit recently, unused tokens built up in the bucket, and that reserve absorbs a short spike without any request failing, exactly the point of separating burst capacity from steady-state rate. Rejection (a 429 response) only starts once the bucket is actually empty, every accumulated token has been consumed and the spike is sustained long enough that the rate of token consumption keeps exceeding the rate of token replenishment. This is why a token bucket, unlike a hard per-second cap, tolerates brief bursts gracefully while still enforcing a real steady-state ceiling.

SQL Joins & Query Planning

Why would a hash join beat a nested loop join for two large, unindexed tables, but lose to a nested loop join when one table is tiny?

A nested loop join's cost scales with (outer rows) × (cost of an inner-side lookup per row), so with two large unindexed tables, the inner-side scan is expensive and gets repeated for every single outer row, making the total cost grow multiplicatively. A hash join instead pays a roughly one-time cost to build a hash table from one side, then does a cheap lookup per row from the other side, additive rather than multiplicative, which wins decisively at scale. But when one table is tiny, the nested loop's "repeat the inner scan per outer row" cost is trivial regardless, and it avoids the hash table's build overhead entirely, so the simpler algorithm wins for small inputs specifically.

Web Accessibility Fundamentals

A custom dropdown built entirely from styled divs passes a visual design review. What is likely still broken for a keyboard-only or screen-reader user, and why doesn't looking right catch it?

Without the correct ARIA roles/states (or, better, a native `<select>`), a div-based dropdown typically has no way to be reached or operated via keyboard alone (no built-in Tab/Enter/Arrow-key handling), and a screen reader has no semantic information telling it "this is a dropdown, it is currently closed, here are its options," so it may announce nothing meaningful at all. A purely visual review can't catch this because the div looks and behaves correctly with a mouse, the missing behavior only surfaces via keyboard navigation or assistive technology, which is exactly why accessibility has to be tested directly with a keyboard and a screen reader, not inferred from how a component looks.

Search results for “databases” | Cloud Tech by Victor