π― Exam Tip
β Athena is serverless
β Queries data directly from S3
β Uses standard SQL
β No need to load data into a database first
β Common for analytics, reporting, and analyzing AWS logs
β "Serverless SQL on S3 data" β Athena
π Amazon Athena
Organizations store lots of data in S3 β logs, CSVs, JSON, reports β but storing isn't enough; you need to analyze it too.
Athena is a serverless interactive query service that runs standard SQL directly on data in S3 β no loading or moving the data anywhere.
βοΈ How It Works
1οΈβ£ Store data files in S3 β 2οΈβ£ Open Athena β 3οΈβ£ Write a SQL query β 4οΈβ£ Athena reads the files from S3 β 5οΈβ£ Get your results.
<meta charset="utf-8">
<!-- Athena queries data directly in S3 β no ETL, no copying into another database. Self-contained, drop into codeveda.dev. -->
<div class="infographic-athena">
<header class="at-head">
<div class="at-controls">
<button class="at-btn at-play" type="button" aria-label="Play">
<svg class="icon-play" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="6 3 20 12 6 21 6 3"/></svg>
<svg class="icon-pause" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="6" y="4" width="4" height="16" rx="1"/><rect x="14" y="4" width="4" height="16" rx="1"/></svg>
<span class="at-btn-label">Play</span>
</button>
<button class="at-btn at-restart" type="button" aria-label="Restart">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 12a9 9 0 1 0 3-6.7"/><path d="M3 4v5h5"/></svg>
</button>
</div>
<p class="at-status" aria-live="polite"> </p>
</header>
<div class="at-canvas">
<svg viewBox="0 0 960 540" xmlns="http://www.w3.org/2000/svg" class="at-svg">
<defs>
<marker id="at-arrow" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
<path d="M0,0 L10,5 L0,10 z" class="arrow-fill"/>
</marker>
</defs>
<!-- ===== S3 ===== -->
<g id="at-s3-node">
<circle id="at-ring-s3" cx="150" cy="270" r="52" class="hit-ring hit-ring--s3"/>
<rect x="115" y="235" width="70" height="70" rx="16" class="tile tile--s3"/>
<g transform="translate(150,270)">
<g stroke="var(--paper)" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" fill="none">
<ellipse cx="0" cy="-16" rx="17" ry="4.5"/>
<path d="M-17,-16 -13,17 H13 L17,-16"/>
</g>
</g>
</g>
<text x="150" y="330" text-anchor="middle" class="node-title node-title--s3">Amazon S3</text>
<g id="at-file-chips">
<rect x="75" y="342" width="46" height="20" rx="10" class="chip chip--s3"/>
<text x="98" y="356" text-anchor="middle" class="chip-text">CSV</text>
<rect x="127" y="342" width="46" height="20" rx="10" class="chip chip--s3"/>
<text x="150" y="356" text-anchor="middle" class="chip-text">JSON</text>
<rect x="179" y="342" width="62" height="20" rx="10" class="chip chip--s3"/>
<text x="210" y="356" text-anchor="middle" class="chip-text">Parquet</text>
</g>
<text x="150" y="382" text-anchor="middle" class="pin-note">data stays here β never copied</text>
<!-- arrow S3 -> Athena -->
<line id="at-conn-1" x1="232" y1="270" x2="358" y2="270" class="connector" marker-end="url(#at-arrow)"/>
<path id="at-path-1" d="M234,270 L356,270" fill="none" stroke="none"/>
<circle r="6" class="pulse pulse--read" id="at-pulse-1" opacity="0"><animateMotion id="at-motion-1" dur="0.6s" begin="indefinite" fill="freeze" calcMode="linear"><mpath href="#at-path-1"/></animateMotion></circle>
<!-- ===== Athena ===== -->
<g id="at-athena-node">
<circle id="at-ring-athena" cx="480" cy="270" r="52" class="hit-ring hit-ring--athena"/>
<rect x="445" y="235" width="70" height="70" rx="16" class="tile tile--athena"/>
<g transform="translate(480,270)">
<g stroke="var(--paper)" stroke-width="2.3" stroke-linecap="round" stroke-linejoin="round" fill="none">
<circle cx="-3" cy="-3" r="12"/>
<line x1="6" y1="6" x2="16" y2="16"/>
</g>
</g>
</g>
<text x="480" y="330" text-anchor="middle" class="node-title node-title--athena">Amazon Athena</text>
<text x="480" y="348" text-anchor="middle" class="node-caption">Serverless SQL</text>
<g id="at-query-chip" opacity="0">
<rect x="392" y="140" width="176" height="44" rx="8" class="query-box"/>
<text x="404" y="158" class="query-text">SELECT * FROM logs</text>
<text x="404" y="174" class="query-text">WHERE date = today()<tspan id="at-cursor" class="cursor">|</tspan></text>
</g>
<line x1="480" y1="184" x2="480" y2="232" class="query-stem"/>
<!-- arrow Athena -> Results -->
<line id="at-conn-2" x1="562" y1="270" x2="688" y2="270" class="connector" marker-end="url(#at-arrow)"/>
<path id="at-path-2" d="M564,270 L686,270" fill="none" stroke="none"/>
<circle r="6" class="pulse pulse--results" id="at-pulse-2" opacity="0"><animateMotion id="at-motion-2" dur="0.6s" begin="indefinite" fill="freeze" calcMode="linear"><mpath href="#at-path-2"/></animateMotion></circle>
<!-- ===== Results ===== -->
<g id="at-results-node">
<circle id="at-ring-results" cx="810" cy="270" r="52" class="hit-ring hit-ring--results"/>
<rect x="775" y="235" width="70" height="70" rx="16" class="tile tile--results"/>
<g id="at-result-bars" transform="translate(810,270)">
<g stroke="var(--paper)" stroke-width="2.4" stroke-linecap="round" fill="none">
<line class="rbar" x1="-14" y1="16" x2="-14" y2="4"/>
<line class="rbar" x1="0" y1="16" x2="0" y2="-8"/>
<line class="rbar" x1="14" y1="16" x2="14" y2="-14"/>
</g>
</g>
</g>
<text x="810" y="330" text-anchor="middle" class="node-title node-title--results">Query Results</text>
<text x="810" y="348" text-anchor="middle" class="node-caption">/ Analytics</text>
</svg>
</div>
</div>
<style>
.infographic-athena {
--ink: #1a1a1a;
--ink-soft: #5c5c5c;
--paper: #ffffff;
--paper-alt: #f6f4ef;
--line: #e2ddd0;
--s3: #2f8659;
--s3-soft: #e2f3ea;
--athena: #d6482f;
--athena-soft:#fce7e1;
--results: #2563eb;
--results-soft: #e3ebfd;
--accent: #2563eb;
--display-font: 'Fraunces', Georgia, serif;
--body-font: 'Inter', system-ui, -apple-system, sans-serif;
box-sizing: border-box;
max-width: 960px;
margin: 0 auto;
font-family: var(--body-font);
color: var(--ink);
background: var(--paper);
}
.infographic-athena[data-theme="dark"] {
--ink: #e8e6e1;
--ink-soft: #9a968c;
--paper: #121212;
--paper-alt: #1c1c22;
--line: #2c313d;
--s3: #5cb787;
--s3-soft: #17281f;
--athena: #e8896f;
--athena-soft:#33201b;
--results: #5b8def;
--results-soft:#1c2740;
--accent: #5b8def;
}
.infographic-athena * { box-sizing: border-box; }
.infographic-athena .at-head { text-align: center; padding: 0.5rem clamp(1rem, 4vw, 2rem) 0.25rem; }
.infographic-athena .at-controls { display: inline-flex; align-items: center; gap: 0.6rem; }
.infographic-athena .at-btn {
display: inline-flex; align-items: center; gap: 0.45rem;
background: var(--accent); color: var(--paper); border: none; border-radius: 999px;
padding: 0.55rem 1.1rem; font-family: inherit; font-size: 0.88rem; font-weight: 600;
cursor: pointer; transition: opacity 0.15s;
}
.infographic-athena .at-btn:hover { opacity: 0.88; }
.infographic-athena .at-restart { background: var(--paper-alt); color: var(--ink); border: 1px solid var(--line); padding: 0.55rem 0.7rem; }
.infographic-athena .at-btn svg { width: 15px; height: 15px; }
.infographic-athena .icon-pause { display: none; }
.infographic-athena .at-play.is-playing .icon-play { display: none; }
.infographic-athena .at-play.is-playing .icon-pause { display: inline-block; }
.infographic-athena .at-status { margin: 0.6rem 0 0; font-size: 0.88rem; font-weight: 600; color: var(--ink-soft); min-height: 1.2em; }
.infographic-athena .at-canvas { padding: 0 clamp(0.75rem, 3vw, 2rem) 1rem; }
.infographic-athena .at-svg { width: 100%; aspect-ratio: 16 / 9; height: auto; display: block; overflow: visible; }
.infographic-athena .tile--s3 { fill: var(--s3); }
.infographic-athena .tile--athena { fill: var(--athena); }
.infographic-athena .tile--results { fill: var(--results); }
.infographic-athena .hit-ring { fill: none; stroke-width: 3; stroke-dasharray: 8 7; opacity: 0; transform-box: fill-box; transform-origin: center; }
.infographic-athena .hit-ring--s3 { stroke: var(--s3); }
.infographic-athena .hit-ring--athena { stroke: var(--athena); }
.infographic-athena .hit-ring--results { stroke: var(--results); }
.infographic-athena .hit-ring.is-active { opacity: 0.75; animation: at-ring-pop 0.7s ease-out forwards; }
@keyframes at-ring-pop { 0% { opacity: 0.9; transform: scale(0.85); } 100% { opacity: 0; transform: scale(1.18); } }
.infographic-athena .hit-ring.is-holding { opacity: 0.4; }
.infographic-athena .node-title { font-family: var(--display-font); font-weight: 700; font-size: 16px; }
.infographic-athena .node-title--s3 { fill: var(--s3); }
.infographic-athena .node-title--athena { fill: var(--athena); }
.infographic-athena .node-title--results { fill: var(--results); }
.infographic-athena .node-caption { font-size: 12px; fill: var(--ink-soft); font-family: var(--body-font); }
.infographic-athena .chip { fill: var(--s3-soft); stroke: var(--s3); stroke-width: 1; opacity: 0.5; transition: opacity 0.3s; }
.infographic-athena .chip-text { font-size: 10.5px; fill: var(--s3); font-family: var(--body-font); font-weight: 600; text-anchor: middle; opacity: 0.65; transition: opacity 0.3s; }
.infographic-athena #at-file-chips.is-lit .chip { opacity: 1; }
.infographic-athena #at-file-chips.is-lit .chip-text { opacity: 1; }
.infographic-athena .pin-note { font-size: 11px; fill: var(--ink-soft); font-style: italic; font-family: var(--body-font); }
.infographic-athena .connector { stroke: var(--line); stroke-width: 1.75; fill: none; }
.infographic-athena .connector.is-flowing { stroke-width: 2.5; stroke-dasharray: 6 4; animation: at-flow 0.6s linear infinite; }
.infographic-athena .connector.is-flowing.read-flow { stroke: var(--s3); }
.infographic-athena .connector.is-flowing.results-flow { stroke: var(--results); }
@keyframes at-flow { to { stroke-dashoffset: -20; } }
.infographic-athena .arrow-fill { fill: var(--line); }
.infographic-athena .pulse--read { fill: var(--s3); }
.infographic-athena .pulse--results { fill: var(--results); }
.infographic-athena .query-box { fill: var(--athena-soft); stroke: var(--athena); stroke-width: 1.25; transition: opacity 0.3s; }
.infographic-athena .query-stem { stroke: var(--athena); stroke-width: 1.25; stroke-dasharray: 3 3; opacity: 0.5; }
.infographic-athena .query-text { font-family: 'Courier New', monospace; font-size: 11px; fill: var(--athena); }
.infographic-athena .cursor { animation: at-blink 1s step-end infinite; }
@keyframes at-blink { 50% { opacity: 0; } }
.infographic-athena #at-query-chip { transition: opacity 0.3s; }
.infographic-athena .rbar { transition: transform 0.4s ease; transform-box: fill-box; transform-origin: bottom; transform: scaleY(0); }
.infographic-athena #at-result-bars.is-shown .rbar { transform: scaleY(1); }
@media (prefers-reduced-motion: reduce) {
.infographic-athena * { transition-duration: 0.001ms !important; animation-duration: 0.001ms !important; }
}
</style>
<script>
(function () {
var wrapper = document.currentScript.closest('.infographic-athena')
|| document.querySelector('.infographic-athena');
var bodyAttr = document.body.getAttribute('data-darkmode');
var dark;
if (bodyAttr === 'true') { dark = true; }
else if (bodyAttr === 'false') { dark = false; }
else {
var match = document.cookie.match(/(?:^|;\s*)darkMode=([^;]+)/);
dark = match ? match[1] === 'true' : false;
}
if (dark) wrapper.setAttribute('data-theme', 'dark');
var reducedMotion = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
var playBtn = wrapper.querySelector('.at-play');
var playLabel = wrapper.querySelector('.at-btn-label');
var restartBtn = wrapper.querySelector('.at-restart');
var statusEl = wrapper.querySelector('.at-status');
var ringS3 = wrapper.querySelector('#at-ring-s3');
var ringAthena = wrapper.querySelector('#at-ring-athena');
var ringResults = wrapper.querySelector('#at-ring-results');
var fileChips = wrapper.querySelector('#at-file-chips');
var queryChip = wrapper.querySelector('#at-query-chip');
var resultBars = wrapper.querySelector('#at-result-bars');
var conn1 = wrapper.querySelector('#at-conn-1');
var conn2 = wrapper.querySelector('#at-conn-2');
var pulse1 = wrapper.querySelector('#at-pulse-1');
var pulse2 = wrapper.querySelector('#at-pulse-2');
var motion1 = wrapper.querySelector('#at-motion-1');
var motion2 = wrapper.querySelector('#at-motion-2');
var STEPS = [
'\u2460 Store data files in S3',
'\u2461 Open Athena',
'\u2462 Write a SQL query',
'\u2463 Athena reads the files from S3',
'\u2464 Get your results'
];
function setStatus(text) { statusEl.textContent = text; }
function flashRing(ring) {
ring.classList.remove('is-active');
void ring.offsetWidth;
ring.classList.add('is-active');
}
function fire(motion, pulse, dur) {
motion.setAttribute('dur', (dur / 1000) + 's');
pulse.setAttribute('opacity', reducedMotion ? '0' : '1');
try { motion.beginElement(); } catch (e) {}
}
var timers = [];
var playing = false;
function after(ms, fn) { timers.push(setTimeout(fn, ms)); }
function clearTimers() { timers.forEach(clearTimeout); timers = []; }
function resetVisuals() {
[ringS3, ringAthena, ringResults].forEach(function (r) { r.classList.remove('is-active'); });
fileChips.classList.remove('is-lit');
queryChip.setAttribute('opacity', '0');
resultBars.classList.remove('is-shown');
conn1.classList.remove('is-flowing', 'read-flow');
conn2.classList.remove('is-flowing', 'results-flow');
pulse1.setAttribute('opacity', '0');
pulse2.setAttribute('opacity', '0');
}
var speed = reducedMotion ? 0.4 : 1;
var stepHold = 700 * speed;
var queryHold = 1000 * speed;
var travelDur = 620 * speed;
var resultHold = 1300 * speed;
var loopGap = 700 * speed;
function runCycle() {
if (!playing) return;
var t = 0;
// Step 1: store data in S3
after(t, function () {
setStatus(STEPS[0]);
flashRing(ringS3);
fileChips.classList.add('is-lit');
});
t += stepHold;
// Step 2: open Athena
after(t, function () {
setStatus(STEPS[1]);
flashRing(ringAthena);
});
t += stepHold;
// Step 3: write SQL
after(t, function () {
setStatus(STEPS[2]);
queryChip.setAttribute('opacity', '1');
});
t += queryHold;
// Step 4: Athena reads from S3 (pulse travels S3 -> Athena)
after(t, function () {
setStatus(STEPS[3]);
queryChip.setAttribute('opacity', '0');
conn1.classList.add('is-flowing', 'read-flow');
flashRing(ringS3);
fire(motion1, pulse1, travelDur);
});
t += travelDur;
after(t, function () {
conn1.classList.remove('is-flowing', 'read-flow');
pulse1.setAttribute('opacity', '0');
flashRing(ringAthena);
});
t += 300 * speed;
// Step 5: get results (pulse travels Athena -> Results)
after(t, function () {
setStatus(STEPS[4]);
conn2.classList.add('is-flowing', 'results-flow');
fire(motion2, pulse2, travelDur);
});
t += travelDur;
after(t, function () {
conn2.classList.remove('is-flowing', 'results-flow');
pulse2.setAttribute('opacity', '0');
flashRing(ringResults);
resultBars.classList.add('is-shown');
});
t += resultHold;
after(t, function () {
setStatus('Data stayed in S3 the whole time \u2014 no copying');
resultBars.classList.remove('is-shown');
fileChips.classList.remove('is-lit');
});
t += loopGap;
after(t, function () { if (playing) runCycle(); });
}
function play() {
if (playing) return;
playing = true;
playBtn.classList.add('is-playing');
playLabel.textContent = 'Pause';
runCycle();
}
function pause() {
playing = false;
clearTimers();
playBtn.classList.remove('is-playing');
playLabel.textContent = 'Play';
}
function restart() {
clearTimers();
resetVisuals();
setStatus('\u00A0');
if (playing) { runCycle(); }
}
playBtn.addEventListener('click', function () {
if (playing) { pause(); } else { play(); }
});
restartBtn.addEventListener('click', restart);
})();
</script>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Fraunces:wght@500;600;700&family=Inter:wght@400;500;600&display=swap" rel="stylesheet">The data stays in S3 the whole time β no copying into another database.
π Supported File Formats
CSV, JSON, ORC, Avro, Parquet.
(Athena runs on the Presto query engine β not required knowledge for the exam.)
π QuickSight Integration
Query with Athena, then visualize with Amazon QuickSight:
<meta charset="utf-8">
<!-- QuickSight streams dashboards, Athena queries S3, S3 loads data to users. Self-contained, drop into codeveda.dev. -->
<div class="infographic-qsflow">
<header class="qf-head">
<div class="qf-controls">
<button class="qf-btn qf-play" type="button" aria-label="Play">
<svg class="icon-play" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="6 3 20 12 6 21 6 3"/></svg>
<svg class="icon-pause" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="6" y="4" width="4" height="16" rx="1"/><rect x="14" y="4" width="4" height="16" rx="1"/></svg>
<span class="qf-btn-label">Play</span>
</button>
<button class="qf-btn qf-restart" type="button" aria-label="Restart">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 12a9 9 0 1 0 3-6.7"/><path d="M3 4v5h5"/></svg>
</button>
</div>
<p class="qf-status" aria-live="polite"> </p>
</header>
<div class="qf-canvas">
<svg viewBox="0 0 960 540" xmlns="http://www.w3.org/2000/svg" class="qf-svg">
<defs>
<marker id="qf-arrow" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
<path d="M0,0 L10,5 L0,10 z" class="arrow-fill"/>
</marker>
<linearGradient id="qf-purple-grad" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="var(--purple-a)"/>
<stop offset="100%" stop-color="var(--purple-b)"/>
</linearGradient>
</defs>
<!-- ===== QuickSight ===== -->
<g id="qf-qs-node">
<circle id="qf-ring-qs" cx="120" cy="258" r="72" class="hit-ring hit-ring--purple"/>
<rect x="66" y="206" width="104" height="104" rx="20" class="tile tile--purple"/>
<g transform="translate(120,258) scale(1.45)">
<g stroke="var(--paper)" stroke-width="2.1" stroke-linecap="round" stroke-linejoin="round" fill="none">
<rect x="-16" y="-16" width="32" height="32"/>
<path d="M-10,8 -2,0 4,5 12,-9"/>
<path d="M5,-9 H12 V-2"/>
<circle cx="-10" cy="8" r="1.8" fill="var(--paper)" stroke="none"/>
<circle cx="-2" cy="0" r="1.8" fill="var(--paper)" stroke="none"/>
<circle cx="4" cy="5" r="1.8" fill="var(--paper)" stroke="none"/>
</g>
</g>
</g>
<text x="120" y="330" text-anchor="middle" class="node-title node-title--purple">Amazon</text>
<text x="120" y="352" text-anchor="middle" class="node-title node-title--purple">QuickSight</text>
<!-- arrow QuickSight -> Athena -->
<line id="qf-conn-1" x1="200" y1="258" x2="293" y2="258" class="connector" marker-end="url(#qf-arrow)"/>
<path id="qf-path-1" d="M202,258 L291,258" fill="none" stroke="none"/>
<circle r="6" class="pulse pulse--purple" id="qf-pulse-1" opacity="0"><animateMotion id="qf-motion-1" dur="0.6s" begin="indefinite" fill="freeze" calcMode="linear"><mpath href="#qf-path-1"/></animateMotion></circle>
<text x="246" y="220" text-anchor="middle" class="edge-label">Streaming &</text>
<text x="246" y="238" text-anchor="middle" class="edge-label">Dashboards</text>
<!-- ===== Athena ===== -->
<g id="qf-athena-node">
<circle id="qf-ring-athena" cx="373" cy="258" r="72" class="hit-ring hit-ring--purple"/>
<rect x="319" y="206" width="104" height="104" rx="20" class="tile tile--purple"/>
<g transform="translate(373,258) scale(1.45)">
<g stroke="var(--paper)" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" fill="none">
<circle cx="-3" cy="-3" r="12"/>
<line x1="6" y1="6" x2="16" y2="16"/>
</g>
</g>
</g>
<text x="373" y="330" text-anchor="middle" class="node-title node-title--purple">Amazon</text>
<text x="373" y="352" text-anchor="middle" class="node-title node-title--purple">Athena</text>
<!-- arrow Athena -> S3 -->
<line id="qf-conn-2" x1="453" y1="258" x2="546" y2="258" class="connector" marker-end="url(#qf-arrow)"/>
<path id="qf-path-2" d="M455,258 L544,258" fill="none" stroke="none"/>
<circle r="6" class="pulse pulse--s3" id="qf-pulse-2" opacity="0"><animateMotion id="qf-motion-2" dur="0.6s" begin="indefinite" fill="freeze" calcMode="linear"><mpath href="#qf-path-2"/></animateMotion></circle>
<text x="499" y="232" text-anchor="middle" class="edge-label">Query & analyze</text>
<!-- ===== S3 Bucket ===== -->
<g id="qf-s3-node">
<circle id="qf-ring-s3" cx="626" cy="258" r="72" class="hit-ring hit-ring--s3"/>
<g transform="translate(626,258) scale(1.5)">
<g stroke="var(--s3)" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" fill="none">
<ellipse cx="0" cy="-19" rx="21" ry="6"/>
<path d="M-21,-19 -16,20 H16 L21,-19"/>
<path d="M8,-14 22,-19 22,-9 8,-4"/>
<circle cx="8" cy="-14" r="1.6" fill="var(--s3)" stroke="none"/>
</g>
</g>
</g>
<text x="626" y="330" text-anchor="middle" class="node-title node-title--s3">Amazon</text>
<text x="626" y="352" text-anchor="middle" class="node-title node-title--s3">S3 Bucket</text>
<!-- arrow S3 -> Users -->
<line id="qf-conn-3" x1="706" y1="258" x2="800" y2="258" class="connector" marker-end="url(#qf-arrow)"/>
<path id="qf-path-3" d="M708,258 L798,258" fill="none" stroke="none"/>
<circle r="6" class="pulse pulse--users" id="qf-pulse-3" opacity="0"><animateMotion id="qf-motion-3" dur="0.6s" begin="indefinite" fill="freeze" calcMode="linear"><mpath href="#qf-path-3"/></animateMotion></circle>
<text x="753" y="232" text-anchor="middle" class="edge-label">load data</text>
<!-- ===== Users ===== -->
<g id="qf-users-node">
<circle id="qf-ring-users" cx="880" cy="258" r="72" class="hit-ring hit-ring--users"/>
<g transform="translate(880,258) scale(1.5)">
<g stroke="var(--ink)" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" fill="none">
<circle cx="0" cy="-16" r="8"/>
<path d="M-13,10 v-2 a13,10 0 0 1 26,0 v2"/>
<circle cx="-16" cy="-4" r="6"/>
<path d="M-27,12 v-1.5 a11,8 0 0 1 14,-8"/>
<circle cx="16" cy="-4" r="6"/>
<path d="M27,12 v-1.5 a11,8 0 0 0 -14,-8"/>
</g>
</g>
</g>
<text x="880" y="330" text-anchor="middle" class="node-title node-title--users">Users</text>
</svg>
</div>
</div>
<style>
.infographic-qsflow {
--ink: #1a1a1a;
--ink-soft: #5c5c5c;
--paper: #ffffff;
--paper-alt: #f6f4ef;
--line: #e2ddd0;
--purple-a: #8a2be8;
--purple-b: #b93ce0;
--s3: #2f8659;
--users-c: #232b36;
--accent: #2563eb;
--display-font: 'Fraunces', Georgia, serif;
--body-font: 'Inter', system-ui, -apple-system, sans-serif;
box-sizing: border-box;
max-width: 960px;
margin: 0 auto;
font-family: var(--body-font);
color: var(--ink);
background: var(--paper);
}
.infographic-qsflow[data-theme="dark"] {
--ink: #e8e6e1;
--ink-soft: #9a968c;
--paper: #121212;
--paper-alt: #1c1c22;
--line: #2c313d;
--purple-a: #9b4fe0;
--purple-b: #c968e6;
--s3: #5cb787;
--users-c: #d8d6d0;
--accent: #5b8def;
}
.infographic-qsflow * { box-sizing: border-box; }
.infographic-qsflow .qf-head { text-align: center; padding: 0.5rem clamp(1rem, 4vw, 2rem) 0.25rem; }
.infographic-qsflow .qf-controls { display: inline-flex; align-items: center; gap: 0.6rem; }
.infographic-qsflow .qf-btn {
display: inline-flex; align-items: center; gap: 0.45rem;
background: var(--accent); color: var(--paper); border: none; border-radius: 999px;
padding: 0.55rem 1.1rem; font-family: inherit; font-size: 0.88rem; font-weight: 600;
cursor: pointer; transition: opacity 0.15s;
}
.infographic-qsflow .qf-btn:hover { opacity: 0.88; }
.infographic-qsflow .qf-restart { background: var(--paper-alt); color: var(--ink); border: 1px solid var(--line); padding: 0.55rem 0.7rem; }
.infographic-qsflow .qf-btn svg { width: 15px; height: 15px; }
.infographic-qsflow .icon-pause { display: none; }
.infographic-qsflow .qf-play.is-playing .icon-play { display: none; }
.infographic-qsflow .qf-play.is-playing .icon-pause { display: inline-block; }
.infographic-qsflow .qf-status { margin: 0.6rem 0 0; font-size: 0.88rem; font-weight: 600; color: var(--ink-soft); min-height: 1.2em; }
.infographic-qsflow .qf-canvas { padding: 0 clamp(0.75rem, 3vw, 2rem) 1rem; }
.infographic-qsflow .qf-svg { width: 100%; aspect-ratio: 16 / 9; height: auto; display: block; overflow: visible; }
.infographic-qsflow .tile--purple { fill: url(#qf-purple-grad); }
.infographic-qsflow .hit-ring { fill: none; stroke-width: 3; stroke-dasharray: 8 7; opacity: 0; transform-box: fill-box; transform-origin: center; }
.infographic-qsflow .hit-ring--purple { stroke: var(--purple-a); }
.infographic-qsflow .hit-ring--s3 { stroke: var(--s3); }
.infographic-qsflow .hit-ring--users { stroke: var(--users-c); }
.infographic-qsflow .hit-ring.is-active { opacity: 0.7; animation: qf-ring-pop 0.7s ease-out forwards; }
@keyframes qf-ring-pop { 0% { opacity: 0.9; transform: scale(0.85); } 100% { opacity: 0; transform: scale(1.18); } }
.infographic-qsflow .node-title { font-family: var(--display-font); font-weight: 700; font-size: 19px; }
.infographic-qsflow .node-title--purple { fill: var(--purple-a); }
.infographic-qsflow .node-title--s3 { fill: var(--s3); }
.infographic-qsflow .node-title--users { fill: var(--users-c); }
.infographic-qsflow .connector { stroke: var(--line); stroke-width: 1.75; fill: none; }
.infographic-qsflow .connector.is-flowing { stroke-width: 2.5; stroke-dasharray: 6 4; animation: qf-flow 0.6s linear infinite; }
.infographic-qsflow .connector.is-flowing.flow-purple { stroke: var(--purple-a); }
.infographic-qsflow .connector.is-flowing.flow-s3 { stroke: var(--s3); }
.infographic-qsflow .connector.is-flowing.flow-users { stroke: var(--users-c); }
@keyframes qf-flow { to { stroke-dashoffset: -20; } }
.infographic-qsflow .arrow-fill { fill: var(--line); }
.infographic-qsflow .pulse--purple { fill: var(--purple-a); }
.infographic-qsflow .pulse--s3 { fill: var(--s3); }
.infographic-qsflow .pulse--users { fill: var(--users-c); }
.infographic-qsflow .edge-label { font-size: 14px; fill: var(--ink-soft); font-family: var(--body-font); font-weight: 600; }
@media (max-width: 640px) {
.infographic-qsflow .edge-label { font-size: 10.5px; }
.infographic-qsflow .node-title { font-size: 13px; }
}
@media (prefers-reduced-motion: reduce) {
.infographic-qsflow * { transition-duration: 0.001ms !important; animation-duration: 0.001ms !important; }
}
</style>
<script>
(function () {
var wrapper = document.currentScript.closest('.infographic-qsflow')
|| document.querySelector('.infographic-qsflow');
var bodyAttr = document.body.getAttribute('data-darkmode');
var dark;
if (bodyAttr === 'true') { dark = true; }
else if (bodyAttr === 'false') { dark = false; }
else {
var match = document.cookie.match(/(?:^|;\s*)darkMode=([^;]+)/);
dark = match ? match[1] === 'true' : false;
}
if (dark) wrapper.setAttribute('data-theme', 'dark');
var reducedMotion = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
var playBtn = wrapper.querySelector('.qf-play');
var playLabel = wrapper.querySelector('.qf-btn-label');
var restartBtn = wrapper.querySelector('.qf-restart');
var statusEl = wrapper.querySelector('.qf-status');
var ringQs = wrapper.querySelector('#qf-ring-qs');
var ringAthena = wrapper.querySelector('#qf-ring-athena');
var ringS3 = wrapper.querySelector('#qf-ring-s3');
var ringUsers = wrapper.querySelector('#qf-ring-users');
var conn1 = wrapper.querySelector('#qf-conn-1');
var conn2 = wrapper.querySelector('#qf-conn-2');
var conn3 = wrapper.querySelector('#qf-conn-3');
var pulse1 = wrapper.querySelector('#qf-pulse-1');
var pulse2 = wrapper.querySelector('#qf-pulse-2');
var pulse3 = wrapper.querySelector('#qf-pulse-3');
var motion1 = wrapper.querySelector('#qf-motion-1');
var motion2 = wrapper.querySelector('#qf-motion-2');
var motion3 = wrapper.querySelector('#qf-motion-3');
var STEPS = ['Streaming & Dashboards', 'Query & analyze', 'load data'];
function setStatus(text) { statusEl.textContent = text; }
function flashRing(ring) {
ring.classList.remove('is-active');
void ring.offsetWidth;
ring.classList.add('is-active');
}
function fire(motion, pulse, dur) {
motion.setAttribute('dur', (dur / 1000) + 's');
pulse.setAttribute('opacity', reducedMotion ? '0' : '1');
try { motion.beginElement(); } catch (e) {}
}
var timers = [];
var playing = false;
function after(ms, fn) { timers.push(setTimeout(fn, ms)); }
function clearTimers() { timers.forEach(clearTimeout); timers = []; }
function resetVisuals() {
[ringQs, ringAthena, ringS3, ringUsers].forEach(function (r) { r.classList.remove('is-active'); });
conn1.classList.remove('is-flowing', 'flow-purple');
conn2.classList.remove('is-flowing', 'flow-s3');
conn3.classList.remove('is-flowing', 'flow-users');
pulse1.setAttribute('opacity', '0');
pulse2.setAttribute('opacity', '0');
pulse3.setAttribute('opacity', '0');
}
var speed = reducedMotion ? 0.4 : 1;
var travelDur = 650 * speed;
var stepHold = 550 * speed;
var loopGap = 700 * speed;
function runCycle() {
if (!playing) return;
var t = 0;
after(t, function () {
setStatus(STEPS[0]);
flashRing(ringQs);
conn1.classList.add('is-flowing', 'flow-purple');
fire(motion1, pulse1, travelDur);
});
t += travelDur;
after(t, function () {
conn1.classList.remove('is-flowing', 'flow-purple');
pulse1.setAttribute('opacity', '0');
flashRing(ringAthena);
});
t += stepHold;
after(t, function () {
setStatus(STEPS[1]);
conn2.classList.add('is-flowing', 'flow-s3');
fire(motion2, pulse2, travelDur);
});
t += travelDur;
after(t, function () {
conn2.classList.remove('is-flowing', 'flow-s3');
pulse2.setAttribute('opacity', '0');
flashRing(ringS3);
});
t += stepHold;
after(t, function () {
setStatus(STEPS[2]);
conn3.classList.add('is-flowing', 'flow-users');
fire(motion3, pulse3, travelDur);
});
t += travelDur;
after(t, function () {
conn3.classList.remove('is-flowing', 'flow-users');
pulse3.setAttribute('opacity', '0');
flashRing(ringUsers);
});
t += stepHold + loopGap;
after(t, function () { if (playing) runCycle(); });
}
function play() {
if (playing) return;
playing = true;
playBtn.classList.add('is-playing');
playLabel.textContent = 'Pause';
runCycle();
}
function pause() {
playing = false;
clearTimers();
playBtn.classList.remove('is-playing');
playLabel.textContent = 'Play';
}
function restart() {
clearTimers();
resetVisuals();
setStatus('\u00A0');
if (playing) { runCycle(); }
}
playBtn.addEventListener('click', function () {
if (playing) { pause(); } else { play(); }
});
restartBtn.addEventListener('click', restart);
})();
</script>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Fraunces:wght@500;600;700&family=Inter:wght@400;500;600&display=swap" rel="stylesheet">Build reports and dashboards from S3 data with zero database infrastructure to manage.
Pay-per-query β you're charged based on the amount of data scanned (~$5 per TB), not for servers.
π‘ Scan less, pay less: compress files and use efficient columnar formats like Parquet or ORC to cut costs and boost performance.
Business intelligence
Data analytics & reporting
Querying S3 data
Analyzing VPC Flow Logs, ELB logs, CloudTrail logs, and app/platform logs
Serverless makes it ideal for occasional or on-demand analysis with no infrastructure to manage.
π Why Choose Athena?
Analyze files already in S3
Use familiar SQL
Skip managing database servers
Pay only for queries you run
π Summary
π Athena = serverless query service
ποΈ Analyzes data directly in S3
π¬ Uses SQL
π Supports CSV, JSON, ORC, Avro, Parquet
π Integrates with QuickSight for dashboards
π° Charges by data scanned β compressed/columnar formats save money
π― Exam takeaway: "Serverless SQL queries on S3 data" β Amazon Athena